Skip to content

[Bugfix] Fall back to T1 when ARC cannot reclaim enough entries from T2 - #55461

Merged
orozery merged 1 commit into
vllm-project:mainfrom
zupengwang:codex/arc-eviction-fallback
Sep 6, 2026
Merged

[Bugfix] Fall back to T1 when ARC cannot reclaim enough entries from T2#55461
orozery merged 1 commit into
vllm-project:mainfrom
zupengwang:codex/arc-eviction-fallback

Conversation

@zupengwang

Copy link
Copy Markdown
Contributor

Purpose

CPU KV offload stores can fail even when ARC has enough evictable entries. When T1 is below its adaptive target, eviction prefers T2 but currently returns None once T2 has no eligible candidates. This also occurs partway through a batch, or when T2 entries are pinned or protected.

Fall back to eligible T1 entries after exhausting T2. Preserve the existing preference order, monotonic queue scans, pin/protection rules, and atomic failure when the total candidate count is insufficient. Add six parameterized cases to the existing manager suite using normal stores and ghost hits to reproduce the adaptive state.

Duplicate-work checks on 2026-09-05 found no open PR implementing this CPU ARC fallback. #50422 adds session-aware policy context without fixing this selection path; #40270 targets GPU BlockPool ARC; #51787 concerns LRU transfer ordering. This change preserves the single-pass optimization merged in #50992.

AI assistance was used to investigate, implement, and test this change.

Test Plan

Tested against upstream 7fbd44cbe0a90b9c8fd3a94a0f0401ac4b1bc719 on Linux with Python 3.12.13 and PyTorch 2.13.0+cu130. The isolated checkout imports its own upstream Python source and reuses dependencies and binary extensions from an existing vLLM 0.28.0 installation.

# Baseline: original ARC implementation with the new regression test.
CUDA_VISIBLE_DEVICES="" OMP_NUM_THREADS=1 .venv/bin/python -m pytest -q tests/v1/kv_offload/cpu/test_manager.py -k test_store_falls_back_to_t1_when_t2_cannot_satisfy_eviction --timeout=60

# Fixed implementation.
CUDA_VISIBLE_DEVICES="" OMP_NUM_THREADS=1 .venv/bin/python -m pytest -q tests/v1/kv_offload/cpu/test_manager.py --timeout=60
CUDA_VISIBLE_DEVICES="" OMP_NUM_THREADS=1 .venv/bin/python -m pytest -q tests/v1/kv_offload/cpu/policies/test_factory.py tests/v1/kv_offload/tiering/test_tiering_offloading.py --timeout=60

Test Result

  • Baseline regression: 5 failed, 1 passed. All five requests with sufficient eligible capacity failed; the insufficient-capacity control passed.
  • Fixed manager suite: 34 passed.
  • Policy factory and tiering suites: 62 passed.
  • Ruff check/format, typos, mypy for Python 3.10–3.13, and the applicable repository validation hooks passed individually on the two changed files; git diff --check passed.
  • The bulk pre-commit invocation was blocked during unrelated Actionlint environment installation by TLS/download timeouts. Applicable Python checks were subsequently run individually using the unmodified repository configuration.

These are CPU unit tests. No model evaluation, GPU test, or end-to-end offload throughput benchmark was run; no performance or model-quality claim is made.

Keep CPU offload stores progressing when T2 has no eligible victims,
while preserving pin protection, atomic failure, and single-pass scans.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: fdac5f66-3f38-4baa-a44e-cce495e68e96

📥 Commits

Reviewing files that changed from the base of the PR and between 7fbd44c and 2d7a48f.

📒 Files selected for processing (2)
  • tests/v1/kv_offload/cpu/test_manager.py
  • vllm/v1/kv_offload/cpu/policies/arc.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved cache eviction behavior when the preferred cache segment has no eligible entries.
    • Cache capacity can now be reclaimed from the fallback segment, allowing eligible operations to proceed instead of stopping prematurely.
    • Added validation for eviction ordering, scan boundaries, and atomic behavior when storage operations fail.

Walkthrough

The ARC eviction policy now falls back to T1 when T2 cannot provide an evictable candidate. A parametrized test covers pinned keys, protected keys, eviction results, iterator bounds, and failed-store atomicity.

Changes

ARC eviction fallback

Layer / File(s) Summary
T2-to-T1 eviction fallback and validation
vllm/v1/kv_offload/cpu/policies/arc.py, tests/v1/kv_offload/cpu/test_manager.py
evict scans T1 when T2 yields no candidate and updates virtual_t1_size. The parametrized test verifies eviction outcomes, key ordering, scan bounds, impossible evictions, and post-store lookups.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 2d7a4

ARC eviction now reclaims eligible T1 entries when T2 cannot satisfy a store, while preserving protected-key and failed-store behavior. Targeted regression coverage and the reported suite results support merging without an outstanding current-head risk.

Suggested reviewers: ronensc

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: ARC eviction falls back to T1 when T2 cannot reclaim enough entries.
Description check ✅ Passed The description directly explains the ARC eviction bug, the T1 fallback, preserved behavior, regression coverage, and test results.
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.
  • Fix all pre-merge checks with AI

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.

@mergify mergify Bot added the bug Something isn't working label Sep 5, 2026
@zupengwang
zupengwang marked this pull request as ready for review September 5, 2026 12:32

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@Manny7717 Manny7717 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.

APPROVE — verified locally against head 2d7a48f and base 7fbd44c.

Bug is real. ARCCachePolicy.evict() preferred T2 whenever T1 was below its adaptive target, and returned None (store failure → prepare_store fails) whenever T2 had no eligible candidates — even when T1 held plenty of idle, unprotected blocks. The manager's own _num_evictable_cache_blocks pre-check (manager.py:204) can pass while the policy still returns None, so the store fails despite sufficient reclaimable capacity. This also bites mid-batch and whenever T2 entries are pinned/protected.

Fix verified. After the T2 scan yields nothing, the code now continues the (already-positioned, monotonic) T1 iterator and evicts from T1, decrementing virtual_t1_size so the batch simulation stays consistent. Scans stay single-pass — no quadratic restart.

Regression-proven: the new parametrized test test_store_falls_back_to_t1_when_t2_cannot_satisfy_eviction (transplanted onto base 7fbd44c) fails in 5/6 cases exactly as expected — the store is rejected (output is None) where head now evicts T1 and completes the store. The 6th case (expected_evicted=None) passes on both — correct atomic-failure control. Pinned/protected blocks survive in every case. Full tests/v1/kv_offload/cpu/test_manager.py: 34/34 pass at head (the 5 failures on base are precisely the new cases — zero collateral).

Design note: evicting from T1 when it is below its adaptive target deviates from the pure-ARC 'never shrink T1 under target' rule, but that rule exists to prefer T2 — when T2 cannot satisfy, failing the store is strictly worse, and this matches canonical ARC's empty-T2 fallback. The counting asserts (items_yielded <= len) lock in the no-rescan property.

Non-blocking: the eviction-failure path still returns None when both lists are exhausted of eligible entries, which is correct; nothing further needed here.

@orozery orozery added the ready ONLY add when PR is ready to merge/full CI is needed label Sep 6, 2026
@orozery

orozery commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

/ci run

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

@zupengwang, CI is now available for this PR.

  • /ci run starts upstream CI; /amd-ci run starts AMD CI only.
  • /ci retry retries failed jobs in the CI build for the current PR head. If the current head has no CI build, it starts a new CI build for the current head containing only jobs that failed in the latest earlier CI build for this PR.
  • /amd-ci retry retries failed jobs in AMD CI for the current PR head. Use /amd-ci run when the current head has no AMD CI build.
  • /ci cancel cancels scheduled or running CI builds for this PR branch; /amd-ci cancel does the same for AMD CI only.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87432 for commit 2d7a48f010f9.

@orozery
orozery merged commit dd07601 into vllm-project:main Sep 6, 2026
104 checks passed
ItsRoy69 pushed a commit to ItsRoy69/vllm that referenced this pull request Sep 10, 2026
…T2 (vllm-project#55461)

Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Jyotirmoy Roy <jyotirmoyroy649@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ready ONLY add when PR is ready to merge/full CI is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants