Skip to content

[GG] feat(kv-offload): bound filesystem tier capacity#165

Open
yatesdr wants to merge 1 commit into
local-inference-lab:dev/gilded-gnosisfrom
yatesdr:feat/fs-tier-capacity-v20
Open

[GG] feat(kv-offload): bound filesystem tier capacity#165
yatesdr wants to merge 1 commit into
local-inference-lab:dev/gilded-gnosisfrom
yatesdr:feat/fs-tier-capacity-v20

Conversation

@yatesdr

@yatesdr yatesdr commented Jul 22, 2026

Copy link
Copy Markdown

Summary

  • add opt-in max_cache_size_bytes capacity to the filesystem secondary tier
  • index and trim existing block files at startup, then maintain runtime LRU order
  • reserve capacity across concurrent writers so completed plus pending blocks cannot oversubscribe the limit
  • pin lookup hits and queued load sources until eviction is safe
  • emit removal events before replacement store events and document namespace ownership

Why

The filesystem tier currently grows without a configured retention bound. On a local NVMe tier this can fill the device and turn normal KV churn into ENOSPC failures outside the cache policy.

Bounded mode evicts the least-recently-used unpinned block before admitting a store. If every resident block is pinned by an active request or load job, that store fails with ENOSPC instead of evicting an in-use source or exceeding the configured limit. Leaving max_cache_size_bytes unset preserves the existing path.

This does not duplicate an open downstream or upstream capacity PR. The open upstream worker-transfer and CPU-policy changes address different tiers and ownership layers; none provides a byte bound for the local filesystem tier.

Forward-port proof

The current dev/gilded-gnosis versions of all three input files were byte-for-byte identical to the v19 inputs for commit d74c0a6. This commit is therefore an exact replay with no conflict resolution or semantic adaptation. The resulting manager, tests, and documentation are also byte-identical to the previously prepared outputs.

Validation on the v20 tree:

  • VLLM_TARGET_DEVICE=empty python -m pytest -q tests/v1/kv_offload/tiering/test_fs_tier.py: 34 passed
  • VLLM_TARGET_DEVICE=empty python -m pytest -q tests/v1/kv_offload/tiering/test_factory.py tests/v1/kv_offload/tiering/test_tiering_offloading.py: 37 passed
  • pre-commit on all three changed files: all applicable hooks passed, including Ruff, mypy, markdownlint, SPDX, and forbidden-import checks
  • Python compileall: passed
  • git diff --check: passed

Model evaluation is not applicable because this changes filesystem cache retention, not model computation or outputs. Store/load round-trip and promotion-race behavior are covered by the focused tests.

Pending runtime gate

Before moving out of draft, run the prepared CN3 v20 acceptance gate with a small bounded NVMe tier: boot, fill beyond the configured limit, prove LRU eviction under overlapping store/load pressure, verify no in-use source is reclaimed, restart, and prove persisted-index promotion. Runtime evidence and image/source pins will be added here.

AI assistance

OpenAI Codex assisted with investigation, forward-port verification, testing, and PR drafting. The human submitter will review every changed line and complete the target-system runtime gate before requesting merge.

Summary by CodeRabbit

  • New Features

    • Filesystem KV caching can now be limited with max_cache_size_bytes.
    • When capacity is reached, the cache automatically removes least-recently-used, unpinned blocks.
    • Existing cache files are indexed and trimmed when the service starts.
    • Cache capacity is safely coordinated during concurrent loads and stores.
    • Optional KV eviction events now report removed blocks and locality details.
  • Documentation

    • Added configuration guidance, capacity behavior, namespace limitations, locality warnings, and tuning recommendations for filesystem and NVMe storage.

Add an opt-in max_cache_size_bytes limit to the filesystem secondary tier. Track runtime LRU state, reserve capacity across concurrent writers, and pin lookup and queued-load sources so eviction cannot race promotion.

Index and trim existing block files on startup, publish removal events before replacement stores, and document that bounded mode requires exclusive ownership of its cache namespace.

Assisted-by: OpenAI Codex

Signed-off-by: Derek Yates <derek.yates@live.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The filesystem KV tier adds an optional byte capacity limit with startup indexing, LRU eviction, pin-aware concurrent stores and loads, synchronized event handling, and expanded tests and documentation.

Changes

Filesystem cache capacity

Layer / File(s) Summary
Capacity configuration and startup indexing
vllm/v1/kv_offload/tiering/fs/manager.py, tests/v1/kv_offload/tiering/test_fs_tier.py, docs/features/kv_offloading_usage.md
Adds max_cache_size_bytes, validates bounded-cache settings, indexes existing block files at startup, trims the namespace, and documents configuration and tuning behavior.
Bounded stores, loads, and pinning
vllm/v1/kv_offload/tiering/fs/manager.py, tests/v1/kv_offload/tiering/test_fs_tier.py
Reserves store capacity, evicts unpinned LRU blocks, tracks concurrent reservations, handles load failures, and manages request and promotion-job pin lifetimes.
Lifecycle cleanup and event reporting
vllm/v1/kv_offload/tiering/fs/manager.py, tests/v1/kv_offload/tiering/test_fs_tier.py
Updates LRU touches, completion and request cleanup, drain handling, synchronized event collection, and eviction-event ordering tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant FileSystemTierManager
  participant Filesystem
  participant KVEvents
  Request->>FileSystemTierManager: submit_store
  FileSystemTierManager->>FileSystemTierManager: reserve capacity
  FileSystemTierManager->>Filesystem: evict unpinned LRU blocks
  FileSystemTierManager->>Filesystem: write bounded block
  Filesystem-->>FileSystemTierManager: store completion
  FileSystemTierManager->>KVEvents: record removal event
  FileSystemTierManager-->>Request: return completed job
Loading

Suggested reviewers: ronensc, varun-sundar-rabindranath

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding bounded capacity to the filesystem KV-offload tier.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging.

To run CI, PR reviewers can either: Add ready label to the PR or enable auto-merge.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban.

🚀

@yatesdr
yatesdr marked this pull request as ready for review July 23, 2026 05:34
@yatesdr

yatesdr commented Jul 23, 2026

Copy link
Copy Markdown
Author

Runtime validation update (CN3, 2026-07-23): the bounded tier ran through the full cold long-context ladder while an ordered inotify monitor tracked both completed block files and in-flight temporary files. Across 41,334 filesystem events, observed physical cache high-water was 8,589,111,296 bytes against an 8,589,934,592-byte cap: 823,296 bytes under, with zero observed violations. This directly answers the pending-byte question: temporary writes did not push the namespace over capacity. The monitor emitted 7,275 coverage warnings because it was attached to an already populated dynamic directory tree; that limits the monitor formal verdict but does not change the measured ordered high-water. Together with the 71 focused tests, concurrent-writer reservation tests, startup indexing tests, and sustained runtime turnover, the pending runtime gate is complete and this PR is ready for review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
vllm/v1/kv_offload/tiering/fs/manager.py (2)

449-484: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Eviction loop is O(K·N) on the startup-trim path. list(self._cache_lru.items()) is rebuilt on every outer while iteration and the inner loop breaks after a single eviction, so trimming K blocks from an N-entry index costs O(K·N). Runtime stores evict ~1 block each (fine), but trimming a large oversized namespace at startup can be slow. Since the LRU is oldest-first and no pins exist during initialization, you could iterate the ordered view once. Optional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vllm/v1/kv_offload/tiering/fs/manager.py` around lines 449 - 484, Optimize
_evict_until_fits_locked by avoiding reconstruction of self._cache_lru.items()
and restarting the scan after each eviction. Preserve oldest-first eviction and
existing pinned-entry and filesystem-error handling, while using a single
ordered traversal during startup trimming; retain the current failure result
when no evictable entry can satisfy required_bytes.

251-260: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add strict= to all four zip(job_metadata.keys, job_metadata.block_ids) calls (ruff B905). These pair keys with their block offsets and are expected to be equal-length; strict=True clears the lint gate and turns any future length mismatch into a loud error instead of a silently short task set.

  • vllm/v1/kv_offload/tiering/fs/manager.py#L251-L260: add strict=True to both zip() calls in submit_store.
  • vllm/v1/kv_offload/tiering/fs/manager.py#L275-L275: add strict=True to the zip() in the unbounded submit_load branch.
  • vllm/v1/kv_offload/tiering/fs/manager.py#L296-L296: add strict=True to the zip() in the bounded submit_load branch.

Note zip(strict=...) requires Python 3.10+; confirm the repo's declared target and ruff target-version allow it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vllm/v1/kv_offload/tiering/fs/manager.py` around lines 251 - 260, Update both
zip calls in submit_store and the zip calls in the unbounded and bounded
submit_load branches in vllm/v1/kv_offload/tiering/fs/manager.py (lines 251-260,
275, and 296) to use strict=True, preserving the existing key/block pairing.
Confirm the repository Python target and Ruff target-version support Python 3.10
or newer.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@vllm/v1/kv_offload/tiering/fs/manager.py`:
- Around line 449-484: Optimize _evict_until_fits_locked by avoiding
reconstruction of self._cache_lru.items() and restarting the scan after each
eviction. Preserve oldest-first eviction and existing pinned-entry and
filesystem-error handling, while using a single ordered traversal during startup
trimming; retain the current failure result when no evictable entry can satisfy
required_bytes.
- Around line 251-260: Update both zip calls in submit_store and the zip calls
in the unbounded and bounded submit_load branches in
vllm/v1/kv_offload/tiering/fs/manager.py (lines 251-260, 275, and 296) to use
strict=True, preserving the existing key/block pairing. Confirm the repository
Python target and Ruff target-version support Python 3.10 or newer.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 366362b8-2862-4461-8c31-82d4cafdc2d3

📥 Commits

Reviewing files that changed from the base of the PR and between 4a4299c and a1f5cc6.

📒 Files selected for processing (3)
  • docs/features/kv_offloading_usage.md
  • tests/v1/kv_offload/tiering/test_fs_tier.py
  • vllm/v1/kv_offload/tiering/fs/manager.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant