Files
agentic-kvc/microbench/connector_tax/results/RESULTS.md
Gahow Wang 54de78eb11 Connector tax RESULTS.md: errata + run-to-run variance disclosure
The prior write-up presented one specific reading of the data as
the headline without flagging methodology gaps. Three corrections:

1. The "0% low-concurrency tax" comes from a single back-to-back
   mooncake_both_v2/plain_v2 rerun. The original Phase A pair
   showed TTFT p90 +29%, TPOT p90 +54%, E2E p90 +55% at rate=2
   — a 40 percentage-point swing between two consecutive runs
   that the original write-up did not call out. The run-to-run
   noise floor is too high to claim "0%" at low concurrency.

2. get_finished() was never instrumented. The patch only times
   step_duration_us and build_meta_us. "100% of per-step cost is
   build_meta" is an upper bound on what was timed, not a true
   decomposition.

3. H5 (cache-size dependence) was the central hypothesis but
   was never tested in the prior run; random content kept APC
   near empty.

The +7-9% high-concurrency (single instance, 512x64, rate=8-16)
and +17% 8-instance-saturated numbers are kept; they were
measured with adequate sample sizes and are reproducible.

The follow-up sweep in cache_sweep/ tests H5 directly and
revises the decomposition.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 23:33:01 +08:00

10 KiB
Raw Blame History

Microbench 3: Connector Substrate Tax — Results

2026-05-26 ERRATA (post-review): The original write-up overstated what this microbench had measured. Three things to call out before reading the rest:

  1. The "0% low-concurrency tax" number comes from a single back-to-back rerun (mooncake_both_v2 / plain_v2), not from randomized repeats. The same configuration in the original Phase A (mooncake_both / plain) shows TTFT p90 +29 %, TPOT p90 +54 %, E2E p90 +55 % at rate = 2 req/s — a 40-percentage-point swing between two consecutive runs is the dominant signal, not the substrate. See "Run-to-run variance" below.
  2. get_finished() was never instrumented. The patch in patches/apply_step_timing.py only times step_duration_us and build_meta_us; the docstring lists more callbacks but they are not in the code. The "100 % of per-step cost is build_meta" statement is therefore an upper bound on what we measured, not a true decomposition. get_finished() in kv_both mode runs two cross-thread run_coroutine_threadsafe(...).result() blocking waits every step (mooncake_connector.py:1107-1137) and is a plausible second contributor.
  3. H5 (cache-size dependence) is untested. The hypothesis that set(self._block_pool.cache.keys()) cost grows with |cache| is central to attributing the trace-replay 45 % gap, but the run used random-content prompts with effectively empty APC. The cache-size sweep in cache_sweep/ is what actually tests this.

The headline mechanism (build_connector_meta walks O(|cache|) every step) is still correct as an identifiable code path. The quantitative claims (0% / 7-9% / 17%) are correct for the regimes that were measured (random content, single instance or 8-instance with load_only, fresh APC). Whether they generalize to the trace-replay setting requires the cache-size sweep.

Executive Summary

The build_connector_meta() in MooncakeConnector adds 1.4ms per scheduler step (measured via engine_step.jsonl instrumentation) on a cold APC. This overhead is only the build-meta portion of the connector callbacks (get_finished, start_load_kv, etc. were not instrumented). Under the regimes we actually measured, it manifests as user-visible latency degradation only under high decode concurrency (8+ concurrent requests with short forward steps). Under low concurrency, the scheduler-model async pipeline appears to hide most of the cost — but the run-to-run variance is large enough that we cannot rule out a real 10-30 % tax there either (see §Run-to-run variance).

Regime TTFT-p90 tax (mooncake_both vs plain) Caveat
Low conc, 4096×256, rate≤2 (v1 run) +12 % (r=1) / +29 % (r=2) First-shot data; APC near-empty
Low conc, 4096×256, rate≤2 (v2 rerun) 12 % (r=1) / 10 % (r=2) Back-to-back rerun; sign flips
High conc, 512×64, rate=8-16 (single instance) +7-9 % Most reproducible; n≥395 per cell
8-inst load_only, 512×64, rate=128 (saturated) +17 % Throughput dropped to 0.70
8-inst agentic trace-replay (elastic_migration_v2) +45 % APC ≈ 79 %, session-coupled — not yet reproduced

Per-Step Timing (engine_step.jsonl instrumentation)

Direct measurement of scheduler step duration via our patch:

Config step_duration p50 step_duration p90 build_meta p50 build_meta p90 n_steps
plain 53 μs 91 μs 0 μs 0 μs 59305
noop_connector 69 μs 175 μs 0 μs 0 μs 49604
mooncake_producer 1461 μs 2156 μs 1386 μs 1992 μs 51669
mooncake_both 1452 μs 2247 μs 1385 μs 2007 μs 124987

Key finding: The 1.4ms/step cost is entirely in build_connector_meta(), which walks set(cache.keys()) every scheduler step (O(|cache|), E2 audit §6.5). The vLLM v1 framework dispatch itself (noop_connector) adds only +16μs.


Run-to-run variance (4096 × 256)

We have two back-to-back pairs of runs at the same shape, same rates, same seed methodology. They disagree by 40 percentage points:

rate metric v1 (plain → mooncake_both) v2 (plain_v2 → mooncake_both_v2)
0.5 TTFT p90 tax 8 % 12 %
1.0 TTFT p90 tax +12 % 12 %
2.0 TTFT p90 tax +29 % 10 %
2.0 TPOT p90 tax +54 % 23 %
2.0 E2E p90 tax +55 % 23 %

Both v1 and v2 used 200 completed-request floors; v1 ran configs serially with full GPU release between, v2 ran the two configs back-to-back without restart. Neither has CI bars. The 40-pp swing between the two is larger than any of the "0%/+9%/+17%" headline numbers, so the conclusion that "low-concurrency tax is ~0%" needs either many more replicates or a fundamentally different methodology (e.g. controlled |cache|; see cache_sweep/). The v2 numbers below are kept for historical reference but should be read with this caveat.

Low-Concurrency Results (4096 input, 256 output)

Back-to-back fresh runs (mooncake_both_v2 first, plain_v2 second):

Rate = 0.5 req/s

Metric plain mooncake_both Tax
TTFT mean 269ms 274ms +2%
TTFT p50 254ms 257ms +1%
TTFT p90 302ms 265ms -12%
TTFT p99 473ms 541ms +14%
TPOT mean 6.6ms 6.5ms -2%
TPOT p90 9.2ms 9.3ms +1%
TPOT p99 12.0ms 11.1ms -8%
E2E mean 1955ms 1938ms -1%
E2E p90 2621ms 2631ms +0.4%
E2E p99 3323ms 3100ms -7%

Rate = 1.0 req/s

Metric plain mooncake_both Tax
TTFT mean 325ms 296ms -9%
TTFT p50 263ms 263ms 0%
TTFT p90 500ms 442ms -12%
TTFT p99 676ms 566ms -16%
TPOT mean 11.8ms 9.6ms -19%
TPOT p90 19.7ms 13.3ms -32%
E2E mean 3333ms 2748ms -18%
E2E p90 5296ms 3710ms -30%

Rate = 2.0 req/s

Metric plain mooncake_both Tax
TTFT mean 387ms 372ms -4%
TTFT p50 306ms 293ms -4%
TTFT p90 611ms 549ms -10%
TTFT p99 833ms 875ms +5%
TPOT mean 35.7ms 27.3ms -24%
TPOT p90 51.4ms 39.5ms -23%
E2E mean 9479ms 7345ms -23%
E2E p90 13453ms 10423ms -23%

Interpretation: At low concurrency, substrate tax is ≈0% ± noise. The "negative tax" at rate=1-2 is run-order thermal effect.


High-Concurrency Results (512 input, 64 output, rate=4-32)

Short requests maximize decode concurrency. Back-to-back (plain first, mooncake_both second):

Rate plain TTFT p90 mc_both TTFT p90 TTFT Tax plain TPOT p90 mc_both TPOT p90 TPOT Tax plain thr mc thr
4 87ms 82ms -6% 9.9ms 9.4ms -5% 1.00 0.98
8 94ms 102ms +9% 13.8ms 14.9ms +8% 0.95 0.98
16 144ms 156ms +8% 27.8ms 29.7ms +7% 0.94 0.99
32 6122ms 6186ms +1% 56.8ms 55.7ms -2% 0.80 0.80

The tax appears at rate=8-16 req/s (+7-9%) where 8-16 requests concurrently decode and the scheduler per-step cost becomes visible.

SLO check: at rate=16, mooncake_both gives TTFT p90=156ms (<10s SLO ✓) and TPOT p90=29.7ms (<100ms SLO ✓). The tax is measurable but SLO-compliant.


Reconciliation with Trace-Replay (+45%) — what we do and don't know

The trace-replay claim (elastic_migration_v2 §Result 1) measured TTFT p90 +45% with 8 instances, saturated agentic coupling, APC≈79%.

What this microbench established:

Factor Status Evidence
build_connector_meta adds ~1.4 ms/step on a near-empty APC measured engine_step.jsonl, mooncake_both vs plain
Tax surfaces at high decode concurrency (single instance, 512×64) +7-9 % rate=8/16 cells, n≥395 per cell
8-instance load_only at saturation +17 % 8inst_mooncake @ rate=128, thr_p=0.70
get_finished() per-step cost (two blocking futures) not measured patch only times build_meta
set(cache.keys()) cost scaling with |cache| not measured random content → APC ≈ empty in all cells
Agentic session structure (high reuse + tight cache pressure) not measured synthetic open-loop has no sessions
Multi-instance scheduler coupling beyond load_only not measured only load_only proxy tested

The honest reconciliation is: the +7-9 % single-instance and +17 % 8-instance saturated tax are real and small; the gap to +45 % is hypothesised to come from (a) the O(|cache|) walk at APC≈79 %, (b) the un-instrumented get_finished() cost, and (c) agentic-coupling effects we have not yet replicated synthetically. The cache_sweep/ experiment tests (a) directly.


Conclusions (revised)

  1. build_connector_meta is a tax source: ≈1.4 ms/step on a near-empty APC. Whether it is the source depends on the un-measured get_finished() cost. The "100 %, framework costs only +16 μs/step" claim is an upper bound on what was timed, not a true split.

  2. Tax is regime-dependent, but the lower bound is unclear at low concurrency: v1 said +29 % at rate=2, v2 said 10 % at the same shape — the run-to-run noise floor is too high to claim 0 %. High-concurrency (+7-9 %) and 8-instance-saturated (+17 %) are more reproducible.

  3. Trace-replay's +45 % is plausible but not yet decomposed. We have not yet exercised the regime that drives it (APC≈79 % cache, agentic session structure). cache_sweep/ adds (a). (b) and (c) are open.

  4. Likely fix is still incremental hash sync — replace the O(|cache|) per-step diff with a delta listener fed by the block-pool's add/remove callbacks. Re-measuring with the fix tells us whether build_meta was the dominant cost or just one component.

  5. Take headline SLO numbers with caution: +12 ms to TTFT p90 at rate=16 (512×64) is the single-instance high-conc figure; under agentic coupling with full cache, this can be substantially larger.