Skip to content

fix: match SGLang decode retraction order and post-release eviction - #582

Closed
PeaBrane wants to merge 1 commit into
ai-dynamo:mainfrom
PeaBrane:fix/sglang-retraction-order
Closed

PeaBrane wants to merge 1 commit into
ai-dynamo:mainfrom
PeaBrane:fix/sglang-retraction-order

Conversation

@PeaBrane

Copy link
Copy Markdown
Contributor

Why and what changed

SGLang decode retraction currently selects the first shortest-output request and preserves the original survivor order. Native SGLang's length policy uses a stable output/prompt-length ordering, pops the last tie, and evicts newly released cache toward a per-survivor reserve. These differences change victims and subsequent reuse under KV pressure.

Sort once by descending output length then ascending prompt length, retract from the end, retain ordered survivors, and evict toward 20 tokens per survivor after each release. Terminal ghost rows remain in the batch but cannot be retracted. The reserve does not itself cause further retraction.

Review map

  • Risk level: medium; changes pressure behavior and ordering.
  • Start with: crates/core/src/engine/scheduler/sglang/decode.rs, then the decode_retraction regressions.
  • Public or serialized contract changed: no new fields; victim order and KV events intentionally change.
  • Compatibility or rollback concern: an existing pressure-event test now expects post-release reserve eviction of the unprotected prefix; its release snapshot remains separately asserted.

Evidence

  • Tests: cargo test -p aisimulate-core — 2,431 passed, zero failures, 1 ignored. This full suite ran before the final comment/legal-only changes; final-head focused results follow.
  • Final-head focused regressions: cargo test -p aisimulate-core --lib -- engine::scheduler::sglang — 95 passed, zero failures. Nightly formatting and packaged legal-file checks passed.
  • Fast CI: not run.
  • Full CI: not run.
  • CodeRabbit reviewed commit: not reviewed.
  • Codex reviewed commit: 47ef4e6; bounded gap review found no material concern.
  • Negative or boundary cases: output/prompt ordering, last exact tie, survivor ordering, terminal ghosts, and reserve eviction without unnecessary extra retraction. Unchanged-main negative control: 3 expected assertion failures, 1 pass, exit 101 after successful compilation.
  • Expected-value derivation: fixtures exactly exhaust page-size-1 pools, so one known row frees enough space for the remaining next steps; the reserve test separately checks the released cached prefix.
  • Before/after output, trace, benchmark, or golden diff: exact victim/survivor IDs and cached/free token counts.

Modeling or data provenance

Matches SGLang v0.5.20's length-policy order and release reserve. Synthetic fixtures; this does not add native priority or beam scheduling.

Tracking

None.

This pull request and its description were written by Isaac.

SGLang's default `retract_decode` stably sorts the batch by output
length descending and then prompt length ascending, pops victims from
the end (shortest output, then longest prompt, the latest exact tie
first), and keeps the survivors in that sorted order through
`filter_batch(keep_indices=sorted_indices)`. After each release,
`release_req` evicts cached pages toward `SGLANG_RETRACT_DECODE_STEPS`
(20) tokens per remaining request, while only the next decode step's
demand decides whether to retract again
(python/sglang/srt/managers/schedule_batch.py L2191-L2194, L3168-L3245
and L3289-L3292, and mem_cache/common.py L184-L191, at v0.5.20).

The simulator retracted the earliest request with the shortest output,
kept the original batch order, and evicted only for the next step.
Sort once per retraction pass, retract the last row that is not a
host-loop ghost, and evict toward the reserve after each retraction.
Ghost rows stay in the sorted batch but are never retracted. The
pressure-event test's three-page pool now also loses its unprotected
cached page to that eviction.

Signed-off-by: Rudy Pei <yanrpei@gmail.com>
Co-authored-by: Isaac <no-reply@databricks.com>
@PeaBrane
PeaBrane requested review from a team as code owners October 24, 2026 00:38
@copy-pr-bot

copy-pr-bot Bot commented Oct 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between bd2e1b3 and 47ef4e6.

📒 Files selected for processing: 5
  • THIRD_PARTY_NOTICES.md
  • crates/core/src/engine/scheduler/sglang/core.rs
  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
  • python/aisimulate/THIRD_PARTY_NOTICES.md
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.

📜 Recent review details
🧰 Additional context used
📚 Code guidelines: 2
AGENTS.md — configured
REVIEW.md — configured
📓 Path-based instructions: 5
Review scheduler state transitions and event ordering, including cancel, preempt, drain, retry, duplicate, empty, and terminal paths.

⚙️ CodeRabbit configuration file

Files:

  • crates/core/src/engine/scheduler/sglang/core.rs
  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
Verify upstream provenance, license text, collection and overlay hashes, local modification notices, and generated derivative records remain complete and internally consistent.

⚙️ CodeRabbit configuration file

Files:

  • THIRD_PARTY_NOTICES.md
Read REVIEW.md before commenting.

⚙️ CodeRabbit configuration file

Files:

  • THIRD_PARTY_NOTICES.md
  • python/aisimulate/THIRD_PARTY_NOTICES.md
  • crates/core/src/engine/scheduler/sglang/core.rs
  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
Source excerpt: Keep run logs, investigation notes, and benchmark results out of `docs/`; measured evidence belongs under `benchmarks/evidence/`.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • THIRD_PARTY_NOTICES.md
  • python/aisimulate/THIRD_PARTY_NOTICES.md
  • crates/core/src/engine/scheduler/sglang/core.rs
  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
Source excerpt: Binary parquet changes require a machine-readable summary of keys, shapes, units, row counts, coverage, and anomalies plus proof that a real consumer reaches the new data.

📄 CodeRabbit inference engine (REVIEW.md)

Files:

  • THIRD_PARTY_NOTICES.md
  • python/aisimulate/THIRD_PARTY_NOTICES.md
  • crates/core/src/engine/scheduler/sglang/core.rs
  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
🧠 Learnings: 2
📚 Learning: 2026-09-23T02:01:14.212Z
Learnt from: jasonqinzhou
Repo: ai-dynamo/aisimulate PR: 212
File: THIRD_PARTY_NOTICES.md:39-39
Timestamp: 2026-09-23T02:01:14.212Z
Learning: In `THIRD_PARTY_NOTICES.md`, AISimulate file paths are relative to `python/aisimulate/` unless the notice states otherwise. Do not require a `python/aisimulate/` prefix for paths that follow this documented convention.

Applied to files:

  • THIRD_PARTY_NOTICES.md
  • python/aisimulate/THIRD_PARTY_NOTICES.md
📚 Learning: 2026-10-20T16:50:41.000Z
Learnt from: CR
Repo: ai-dynamo/aisimulate PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-10-20T16:50:41.000Z
Learning: Source excerpt:
# AGENTS

## Required Third-Party Attribution

The repository's Apache-2.0 license and NVIDIA copyright header do not replace
an upstream license or attribution requirement. Do not label third-party code
as exclusively NVIDIA-authored. If the source, revision, license, compatibility,
or required notice is unclear, stop and request maintainer or Open Source Review
Board guidance before committing the derived content. This is a required gate,
not optional documentation.

Applied to files:

  • crates/core/src/engine/scheduler/sglang/decode.rs
  • crates/core/src/engine/scheduler/sglang/tests.rs
🔀 Multi-repo context ai-dynamo/dynamo, ai-dynamo/aiconfigurator

Linked repositories findings

ai-dynamo/dynamo

  • Replay exposes kv_event_lag_ms and explicitly models both stored and removed KV-cache events observed by the router; changed eviction/order behavior can therefore alter replay event sequences without changing a serialized schema. [::ai-dynamo/dynamo::components/src/dynamo/replay/api.py:279-285]
  • The SGLang sidecar validates KV-event descriptors, including block size, DP coverage, topic, and publisher endpoint, before forwarding events. The PR’s behavioral changes do not alter this discovery contract. [::ai-dynamo/dynamo::lib/sidecar/sglang/src/engine.rs:781-918]
  • No references to RETRACT_DECODE_STEPS or decode_retraction were found in Dynamo, so there is no direct downstream consumer of the changed scheduler implementation.

ai-dynamo/aiconfigurator

  • The frozen Dynamo 1.2.0 generator contract pins SGLang to 0.5.11 and references its server_args.py; it does not model decode-retraction or cache-eviction behavior. [::ai-dynamo/aiconfigurator::tests/golden/generator/test_release_1_2_0_backend_contracts.py:23-36]
  • The backend version matrix likewise resolves Dynamo 1.2.0 to SGLang 0.5.11, so this repository provides no validation of the PR’s SGLang v0.5.20 behavioral alignment. [::ai-dynamo/aiconfigurator::src/aiconfigurator/generator/config/backend_version_matrix.yaml:11]
📝 Summary

Risk: Medium. Three areas need human attention: decode victim ordering and terminal ghost-row handling; cache eviction after each release; regression-test expectations for victim order and KV events.

Changes

  • Decode retraction now sorts eligible requests by descending output length, then ascending prompt length. It retracts from the end of that order and preserves survivor order.
  • After each release, the scheduler evicts cached pages toward a reserve of running.len() * RETRACT_DECODE_STEPS tokens. The reserve does not itself trigger another retraction.
  • The fresh-prefill pressure test and new decode-retraction tests cover the changed behavior.
  • Third-party notices and source comments document the SGLang v0.5.20 adaptation and its scope.

No public or serialized fields change. The PR objectives state that the change does not add native priority or beam scheduling.

Evidence and readiness

The supplied report says cargo test -p aisimulate-core passed before final comment and legal-file changes, with 2,431 passed, zero failures, and 1 ignored. At final head, the targeted scheduler test run reported 95 passed and zero failures. Nightly formatting and packaged legal-file checks also passed. Fast CI and full CI were not run. These results are reported, not independently verified here.

Technical quality is supported by the reported targeted tests. Merge readiness remains incomplete because full CI was not run. No current bot-review findings were supplied, so review severity counts are unavailable; this summary does not treat that as approval.

The SGLang decode scheduler now uses stable length-based ordering to select retraction victims and evicts cached pages toward a survivor reserve after each retraction. Regression tests cover victim selection, terminal ghost rows, and cache cleanup. Third-party notices document the source and license.

Changes: Decode retraction

Layer / File(s) Summary
Retraction ordering, cache eviction, and regression coverage
crates/core/src/engine/scheduler/sglang/core.rs, crates/core/src/engine/scheduler/sglang/decode.rs, crates/core/src/engine/scheduler/sglang/tests.rs, THIRD_PARTY_NOTICES.md, python/aisimulate/THIRD_PARTY_NOTICES.md
The scheduler stably sorts rows by descending output length and ascending prompt length, then retracts the last eligible request. After retraction, it evicts cached pages toward a reserve of running.len() * RETRACT_DECODE_STEPS; the next capacity check still controls further retractions. Tests cover victim selection, terminal ghost rows, and cache cleanup. Comments and notices identify the SGLang source version, revision, and license.

Priority: ⬇️ Low

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

Merge Risk: ⚪ Minimal · up to 47ef4

No identified issue needs resolution before merge; the changed retraction order does not cause the cache-commit search to miss a remaining request.

Pre-merge checks: Passed 8
Check name Status Explanation
Title check Passed The title precisely identifies the two behavioral changes: SGLang decode retraction order and post-release cache eviction. It is specific and not vague.
Description check Passed The description covers the required sections, behavior change, review map, risk, compatibility, test evidence, provenance, and tracking status. It provides exact commands and results, including the li…
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.
Cross-Layer Contract Passed PASS. The diff changes no public input, schema field, CLI setting, default, or serialization declaration. It changes internal SGLang retraction and cache behavior in decode.rs (lines 243-279), and t…
Modeling And Data Evidence Passed The PR supplies both provenance and reproducible evidence. THIRD_PARTY_NOTICES.md:1447-1466 pins SGLang v0.5.20 commit 94602c9c..., names the upstream source paths and functions, and states the ad…
Compatibility Boundaries Passed No compatibility-boundary failure is introduced. The PR changes only internal SGLang scheduler logic, tests, and synchronized third-party notices. Scheduler implementation items remain pub(crate)/`p…
Review Evidence Passed The PR description names relevant commands and results: cargo test -p aisimulate-core and the focused SGLang test command, with pass counts and zero failures. It includes boundary and negative valid…
Full details: Description check

Explanation

The description covers the required sections, behavior change, review map, risk, compatibility, test evidence, provenance, and tracking status. It provides exact commands and results, including the limitation that full CI was not run.

Full details: Cross-Layer Contract

Explanation

PASS. The diff changes no public input, schema field, CLI setting, default, or serialization declaration. It changes internal SGLang retraction and cache behavior in decode.rs (lines 243-279), and the existing flow still carries pressure_events through DecodeResult, EnginePassResult, and replay evidence without a consumer change (core.rs lines 1396-1400; replay component lines 940-947 and 2593-2605). The added Rust tests cover ordering, stable ties, ghost rows, reserve eviction, and no extra retraction (tests.rs lines 752-828). The cache-commit consumer already handles reordered running requests, and an existing test covers arbitrary running order (tests.rs lines 3507-3524). Documentation and source attribution are updated in both notice files. No Python or CLI consumer is stale because the PR adds no Python/CLI contract.

Full details: Modeling And Data Evidence

Explanation

The PR supplies both provenance and reproducible evidence. THIRD_PARTY_NOTICES.md:1447-1466 pins SGLang v0.5.20 commit 94602c9c..., names the upstream source paths and functions, and states the adaptation scope. The changed pressure regression gives an explicit before/after diff: base expected one removed page and a four-token prefix; head expects two removed pages, eight available tokens, and no prefix (crates/core/src/engine/scheduler/sglang/tests.rs:680-688). New deterministic tests assert exact victim and survivor IDs, tie handling, terminal ghosts, cache prefix eviction, available tokens, and no extra retraction (tests.rs:752-828). The implementation maps those expected outputs to explicit selection and reserve-eviction logic (decode.rs:243-280). This is an explained, reproducible regression fixture with an independently pinned upstream behavioral oracle, not binary-only validation.

Full details: Compatibility Boundaries

Explanation

No compatibility-boundary failure is introduced. The PR changes only internal SGLang scheduler logic, tests, and synchronized third-party notices. Scheduler implementation items remain pub(crate)/pub(super) (crates/core/src/engine/scheduler/sglang/mod.rs:8-18, core.rs:62, decode.rs:24-27), and no Python source, schema, binding, manifest, dependency lock, or version declaration changes are present. The existing reserve default remains 20 tokens and is documented in the changed Rust code. Both notice files are identical. The unchanged release contracts still define one aisimulate wheel and one publishable aisimulate-core crate, with no Dynamo dependency.

Full details: Review Evidence

Explanation

The PR description names relevant commands and results: cargo test -p aisimulate-core and the focused SGLang test command, with pass counts and zero failures. It includes boundary and negative validation for ordering, terminal ghosts, reserve eviction, and an unchanged-main control. It distinguishes local test results, SGLang parity/modeling evidence, and the absence of production serving changes; it also states that Fast CI and Full CI were not run. The reviewed diff changes no workflow files and does not cite an inactive nested workflow as hosted CI evidence.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@PeaBrane

Copy link
Copy Markdown
Contributor Author

Superseded by #583, which now contains this change together with the related SGLang cache lifecycle, eviction, reporting, and KV-event corrections. The consolidated branch has passed local core and public-API validation.

@PeaBrane PeaBrane closed this Oct 24, 2026
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