Skip to content

feat: report first-admission cache reuse per request - #580

Closed
PeaBrane wants to merge 1 commit into
ai-dynamo:mainfrom
PeaBrane:fix/first-admission-reuse-record
Closed

PeaBrane wants to merge 1 commit into
ai-dynamo:mainfrom
PeaBrane:fix/first-admission-reuse-record

Conversation

@PeaBrane

Copy link
Copy Markdown
Contributor

Why and what changed

requests.jsonl reports reused_input_tokens as the largest reuse across a request's prefill admissions. After a preemption, the readmission can reuse KV that the request itself computed, so that value can exceed what the cache actually provided when the request first arrived. The collector already tracks first-admission reuse and uses it for the summary's first_admission_prefix_cache_reused_ratio, but per-request records only expose it through the tier-attributed G1/host fields, which SGLang and other paths without tier attribution leave empty.

This adds first_admission_reused_input_tokens to PerRequestRecord: total prompt tokens reused from all tiers at the first admission, unchanged by later readmissions. Existing fields keep their meaning. The KV-cache docs table now lists both reuse fields and how they relate to the summary ratios.

Review map

  • Risk level: low; one additive report field.
  • Start with: crates/core/src/replay/report.rs, then the new test in crates/core/src/replay/canonical.rs.
  • Public or serialized contract changed: yes, additively. PerRequestRecord gains a public field and per-request JSON gains a key; crates/tests/public-api is updated for the new field.
  • Compatibility or rollback concern: consumers that construct PerRequestRecord literals must set the new field.

Evidence

  • Tests: cargo test -p aisimulate-core passed: 2,429 cases, zero failures, one ignored; cargo test --manifest-path crates/tests/public-api/Cargo.toml passed (external consumer compiled; zero runtime cases). The new canonical_record_preserves_first_admission_reuse_after_readmission test admits a request twice (512 reused tokens, then 25,088 after readmission) and checks the per-request record, admission history and both summary ratios. An existing report test now also checks the new field on a single admission.
  • Fast CI: pending.
  • Full CI: pending; local results above are not hosted CI evidence.
  • CodeRabbit reviewed commit: pending.
  • Codex reviewed commit: 27bae2a; bounded gap review found no material concern.
  • Negative or boundary cases: readmission with larger reuse leaves the first-admission value unchanged; a single admission reports equal values.
  • Expected-value derivation: the test's ratios are 512 / 32,768 and 25,088 / 32,768 by construction.
  • Before/after output, trace, benchmark, or golden diff: per-request JSON gains one key; report digest pins are updated because they hash that JSON. Existing summary semantics are unchanged.

Modeling or data provenance

N/A.

Tracking

None.

This pull request and its description were written by Isaac.

Per-request records report reused_input_tokens as the largest reuse across
prefill admissions, which a readmission after preemption can raise with KV
the request computed itself. The collector already tracks first-admission
reuse for the summary ratio; expose it on PerRequestRecord as
first_admission_reused_input_tokens, so paths without cache-tier attribution,
including SGLang, report it as well.

Re-pin the AgentX snapshot report digests, which hash per-request JSON. With
the new field excluded from serialization, the previous digests still match.

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:37
@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 27bae2a.

📒 Files selected for processing: 5
  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.rs
  • crates/core/tests/agentx_qualification.rs
  • crates/tests/public-api/src/lib.rs
  • docs/replay/engine/kv-cache.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; 11 remain after this review.

📜 Recent review details
🧰 Additional context used
📚 Code guidelines: 3
crates/core/src/replay/CLAUDE.md — auto-discovered
AGENTS.md — configured
REVIEW.md — configured
📓 Path-based instructions: 6
Preserve deterministic Replay semantics and explicit validation.

⚙️ CodeRabbit configuration file

Files:

  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.rs
Check commands, defaults, supported runtimes, public names, and claims against executable behavior.

⚙️ CodeRabbit configuration file

Files:

  • docs/replay/engine/kv-cache.md
Read REVIEW.md before commenting.

⚙️ CodeRabbit configuration file

Files:

  • crates/core/tests/agentx_qualification.rs
  • crates/tests/public-api/src/lib.rs
  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.rs
  • docs/replay/engine/kv-cache.md
Source excerpt: **Tight-spin/livelock extreme:** do not repeatedly report an effect-free, queued-only zero-duration pass as progress at the same virtual timestamp.

📄 CodeRabbit inference engine (crates/core/src/replay/CLAUDE.md)

Files:

  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.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:

  • crates/core/tests/agentx_qualification.rs
  • crates/tests/public-api/src/lib.rs
  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.rs
  • docs/replay/engine/kv-cache.md
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:

  • crates/core/tests/agentx_qualification.rs
  • crates/tests/public-api/src/lib.rs
  • crates/core/src/replay/canonical.rs
  • crates/core/src/replay/report.rs
  • docs/replay/engine/kv-cache.md
🔀 Multi-repo context ai-dynamo/dynamo, ai-dynamo/aiconfigurator

Linked repositories findings

ai-dynamo/dynamo

  • The Python binding forwards the complete PerRequestRecord collection via pythonize, and JSONL serialization uses serde_json::to_string(record), so the new field should propagate without an explicit allowlist change. [::ai-dynamo/dynamo::lib/bindings/python/rust/llm/replay.rs:96-100] [::ai-dynamo/dynamo::lib/bindings/python/rust/llm/replay.rs:875]
  • Dynamo pins both Rust and Python AISimulate artifacts to the exact 0.13.0 development build. The published artifacts used by Dynamo must contain the new field for this boundary to remain compatible. [::ai-dynamo/dynamo::Cargo.toml:54-55] [::ai-dynamo/dynamo::pyproject.toml:15-18] [::ai-dynamo/dynamo::Cargo.lock:36-39]
  • ReplayReport retains per_request as untyped dictionaries and emits it unchanged, so downstream report JSON should automatically include the added key. [::ai-dynamo/dynamo::components/src/dynamo/replay/report.py:62-70]

ai-dynamo/aiconfigurator

  • The migration guide directs replay integrations to AISimulate but defines no per-request report schema, so no compatibility update is indicated there. [::ai-dynamo/aiconfigurator::docs/aisimulate_migration.md:51-66]
📝 Summary

Risk: Medium

Three areas for human attention

  1. Public API compatibility: PerRequestRecord gains the public first_admission_reused_input_tokens: usize field. Check downstream struct literals and consumers for the required update.
  2. First-admission semantics: Confirm the value is captured at the first admission and does not change on readmission. The canonical test checks 512 tokens at first admission and 25,088 after readmission.
  3. Report consistency: Confirm per-request JSON, summary ratios, and the updated AgentX report digests remain consistent. The changes update digest pins and document how the first-admission field differs from total reused tokens.

Behavior and contract

The new field reports prompt tokens reused across tiers at the request’s first admission. Later readmissions can increase reused_input_tokens without changing this field. The field is public and included in per-request reporting. Existing summary semantics are reported unchanged.

Evidence and merge readiness

The supplied change summary reports coverage for canonical serialization, per-request reporting, public API construction, and documentation. It also reports that cargo test -p aisimulate-core and the public API test passed locally. These test results were not independently verified here. Fast and full CI were reported as pending.

Technical evidence supports the intended behavior, but merge readiness is not established until CI results are available. Current review finding counts are unavailable; no review findings were supplied.

Replay reports now include input tokens reused at first admission for each request. Tests verify canonical admission and reuse data, and qualification report hashes and KV-cache documentation are updated.

Changes: Replay reuse reporting

Layer / File(s) Summary
Add the first-admission reuse field
crates/core/src/replay/report.rs, crates/tests/public-api/src/lib.rs, docs/replay/engine/kv-cache.md
PerRequestRecord exposes and populates first_admission_reused_input_tokens. The per-request test, public API test literal, and capture-field documentation include the field.
Verify canonical output and report snapshots
crates/core/src/replay/canonical.rs, crates/core/tests/agentx_qualification.rs
A canonical serialization test checks admission counts, history, reused-token counts, and prefix-cache reuse ratios. Qualification report hashes are updated; expected request counts and labels are unchanged.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • ai-dynamo/aisimulate#578: Adds per-request JSON serialization, which shares the PerRequestRecord serialization contract changed here.
Merge Risk: ⚪ Minimal · up to 27bae

No merge-blocking issue is identified. Complete the normal CI checks before merging.

Pre-merge checks: Passed 8
Check name Status Explanation
Description check Passed The description explains the behavior change, public and serialized contract impact, review map, tests, boundary cases, expected values, documentation changes, and CI status. Required sections are pre…
Title check Passed The title precisely states that the pull request reports first-admission cache reuse per request. It matches the main behavioral change and avoids vague wording.
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 The new output field is traced through all affected layers. Rust stores the first-admission value once at on_admit and emits it in PerRequestRecord (`crates/core/src/replay/report.rs:1567-1596, 93…
Modeling And Data Evidence Passed The PR provides reproducible, machine-readable evidence for the changed reuse selection and ratios. The collector records the first admission value once and keeps the existing maximum-reuse field for …
Compatibility Boundaries Passed The change keeps the public surfaces synchronized. PerRequestRecord adds a serialized Rust field and populates it in per_request_records() (crates/core/src/replay/report.rs:933-1020, 2250-2298),…
Review Evidence Passed The PR description names relevant commands and results: cargo test -p aisimulate-core and the public API manifest test. It includes boundary validation for a single admission and a larger-reuse read…
Full details: Description check

Explanation

The description explains the behavior change, public and serialized contract impact, review map, tests, boundary cases, expected values, documentation changes, and CI status. Required sections are present and sufficiently complete.

Full details: Cross-Layer Contract

Explanation

The new output field is traced through all affected layers. Rust stores the first-admission value once at on_admit and emits it in PerRequestRecord (crates/core/src/replay/report.rs:1567-1596, 938-987, 2250-2295). The derived Serialize path and canonical replay serializer include the field automatically (crates/core/src/replay/canonical.rs:90-120). The Python binding streams each PerRequestRecord through generic JSON serialization (crates/core/src/python.rs:3005-3049), and the CLI forwards the native per_request mappings to requests.jsonl (python/aisimulate/src/aisimulate/main.py:233-241). Documentation lists both reuse fields and their semantics (docs/replay/engine/kv-cache.md:78-93). Tests cover readmission preservation and both summary ratios (crates/core/src/replay/canonical.rs:382-439), single-admission reporting (crates/core/src/replay/report.rs:3198-3215), external public literals (crates/tests/public-api/src/lib.rs:828-855), streamed Python serialization equivalence (crates/core/src/python.rs:5905-5921), and updated output digest consumers (crates/core/tests/agentx_qualification.rs:649-676). The downstream Dynamo binding also treats per-request rows as generic dictionaries and uses generic Python/JSON conversion, so it has no stale field-specific schema (ai-dynamo/dynamo at commit d043ae04174571aeac28dccb156f52d59c3f77fd, lib/bindings/python/rust/llm/replay.rs:96-104, :873-891, components/src/dynamo/replay/report.py:49-70).

Full details: Modeling And Data Evidence

Explanation

The PR provides reproducible, machine-readable evidence for the changed reuse selection and ratios. The collector records the first admission value once and keeps the existing maximum-reuse field for later admissions (crates/core/src/replay/report.rs:1587-1596). The new canonical test constructs admissions of 512 and 25,088 tokens, then verifies both JSON fields, admission history, counts, and both summary ratios (crates/core/src/replay/canonical.rs:384-445). The PR description explains the snapshot hash refresh: per-request JSON gains one key while summary semantics remain unchanged. The updated documentation also states the field provenance and readmission behavior (docs/replay/engine/kv-cache.md:78-94). This is not binary-only validation or an unexplained golden refresh.

Full details: Compatibility Boundaries

Explanation

The change keeps the public surfaces synchronized. PerRequestRecord adds a serialized Rust field and populates it in per_request_records() (crates/core/src/replay/report.rs:933-1020, 2250-2298), while the external public-API fixture copies the field (crates/tests/public-api/src/lib.rs:790-852). The Python binding serializes records generically through Serde (crates/core/src/python.rs:3005-3048), and the CLI writes arbitrary record mappings without a second schema (python/aisimulate/src/aisimulate/output.py:81-87). The replay input schema version is unchanged; the change only extends report output and updates its documentation (docs/replay/engine/kv-cache.md:80-93). Python and Rust remain at version 0.13.0 (python/aisimulate/pyproject.toml:4-7, crates/core/Cargo.toml:4-8), matching the repository's cross-package version contract (python/aisimulate/tests/cross_package/test_core_version_contract.py:39-58). The diff changes no packaging or dependency manifests. Maturin still builds the wheel from the core crate (python/aisimulate/pyproject.toml:104-122), and the documented two-artifact contract remains unchanged (docs/ci/release.md:8-28). AISimulate's workspace and core dependency list contain no Dynamo dependency (Cargo.toml:4-8, 19-33; crates/core/Cargo.toml:19-47). The downstream Dynamo consumer re-exports the record and writes it through Serde rather than constructing literals (ai-dynamo/dynamo@d043ae04174571aeac28dccb156f52d59c3f77fd, lib/mocker/src/replay/mod.rs:19-28, lib/bindings/python/rust/llm/replay.rs:875).

Full details: Review Evidence

Explanation

The PR description names relevant commands and results: cargo test -p aisimulate-core and the public API manifest test. It includes boundary validation for a single admission and a larger-reuse readmission. It clearly labels the reported results as local, states that Fast CI and Full CI are pending, and does not cite inactive nested workflows 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