# DR-fix A/B: hash-sync skip eliminates the O(|cache|) slope

Run: `results/20260526_1543_drfix/`
Compares three configs in a single orchestrated run (same vLLM
process lifecycle order, same machine, same patch stack):

| config | what it does |
|---|---|
| `plain` | no kv connector — control |
| `mooncake_both` | `kv_role=kv_both`, hash sync ON (baseline) |
| `mooncake_both_drfix` | same launcher, but `VLLM_MOONCAKE_DISABLE_DIRECT_READ_SYNC=1` |

The DR-fix patch (`apply_direct_read_fix.py`) replaces the line
`if self._block_pool is not None:` at
`mooncake_connector.py:433` with an env-gated variant that lets us
A/B that single code path without recompiling vLLM. The
`set(self._block_pool.cache.keys())` walk is the only thing it gates.

## Headline

| config | slope (μs / 1k blocks) | step_dur p50 @ \|cache\|=16.6k | build_meta p50 |
|---|---:|---:|---:|
| mooncake_both          | **+81.0** | **1 550 μs** | **1 459 μs** |
| mooncake_both_drfix    | **−0.7** (≈ 0) | **95 μs** | **6 μs** |
| plain (control)        | **−1.8** (≈ 0) | 72 μs | 0 |

The DR-fix kills the slope. mooncake_both_drfix's curve overlays
plain across the full \|cache\| range — see `figure.png`.

![figure](figure.png)

## Savings at the cache ceiling

At \|cache\| ≈ 16.6 k blocks (where the prior run sat for ~ 80 % of
its lifetime, and where the trace-replay run with APC≈79 % would
sit on a same-config H20):

| component | baseline mooncake_both | drfix | saved |
|---|---:|---:|---:|
| `build_connector_meta` p50 | 1 459 μs | 6 μs | **−1 453 μs (−99.6 %)** |
| total step_duration p50 | 1 550 μs | 95 μs | **−1 455 μs (−94 %)** |
| worker `get_finished` p50 | 178 μs | 183 μs | unchanged (this fix doesn't touch it) |
| worker `start_load_kv` p50 | 2 μs | 2 μs | unchanged |

So the patch did **exactly** what the source-code reading
predicted: the O(\|cache\|) walk was the entire scheduler-side cost,
and turning it off recovers all of it. `get_finished` overhead is
untouched — that's a separate fix candidate.

## Throughput (sanity check, not the focus)

| config | requests completed in 241 s | effective rate |
|---|---:|---:|
| plain                  | 322 | 1.34 req/s |
| mooncake_both          | 365 | 1.51 req/s |
| mooncake_both_drfix    | 384 | 1.59 req/s |

Note the plain run had a transient inflight spike (`t+90s inflight=15`)
that other configs did not — this is Poisson-arrival variance, not
a real ordering. The per-step measurements (n ≥ 15 k decode steps
per config) are far more reliable than the request-count totals
for comparing across configs.

## Slope decomposition at each cache bin

| bin | cache mid | plain p50 | mooncake_both p50 | mooncake_both_drfix p50 | drfix tax vs plain |
|---:|---:|---:|---:|---:|---:|
| 1 | 2 629 | 71 | — | 85 | +14 μs |
| 2 | 4 382 | 124 | 655 | 94 | −30 μs |
| 3 | 6 135 | 134 | 809 | 121 | −13 μs |
| 4 | 7 888 | 90 | 1 157 | 101 | +11 μs |
| 5 | 9 640 | 134 | 981 | 150 | +16 μs |
| 6 | 11 393 | 109 | 1 052 | 160 | +51 μs |
| 7 | 13 146 | 124 | 1 228 | 158 | +34 μs |
| 8 | 14 899 | 128 | 1 298 | 132 | +4 μs |
| 9 | 16 652 | 72 | 1 550 | 95 | +23 μs |

mooncake_both_drfix sits **within ±50 μs of plain** at every bin —
that's noise-level. The mooncake_both column rises monotonically
with bin, drfix doesn't. This is the cleanest possible "ablation".

## What this means for the trace-replay 45 %

The prior cache_sweep extrapolation said at \|cache\|≈13 k blocks
(APC≈79 %) the per-step cost is ~ 1.24 ms (1 060 μs build_meta + 180 μs
get_finished). With the DR fix:

```
build_meta (drfix) ≈   6 μs    ← reduced from ~1 060 μs
get_finished       ≈ 180 μs    ← unchanged
total              ≈ 186 μs
```

So the DR fix alone takes the per-step connector cost from
**~1.24 ms to ~0.19 ms** — an **85 % reduction**. On a ~7 ms decode
step that's TPOT inflation dropping from +18 % to +3 %.

If we also fix the `get_finished` constant (the second fix
candidate listed in REPORT.md), per-step cost goes to plain-level
~0 — recovering the entire substrate tax in `kv_both` mode.

## Reproducibility

```
cd microbench/connector_tax/cache_sweep
bash run_drfix.sh         # ~22 min on H20
```

The orchestrator applies v1+v2+DR_FIX patches, runs the three
configs sequentially (the third with the env var set), reverts
all patches on exit, and produces SUMMARY.md + figure.png.

## Implications

1. **The +85 μs / 1k blocks slope was 100 % from our own
   `a7df84b` direct-RDMA-read implementation**, not Mooncake's
   upstream design. Disabling it via env var fully recovers the
   tax.
2. **Direct-read is opt-in by request**: the synthetic workload
   here never sets `direct_read=True`, so the hash sync was doing
   no useful work. Production should gate the sync on
   `direct_read_consumers_present`, or do it incrementally via
   block_pool callbacks rather than per-step diff.
3. **Worker `get_finished` is the next target**: still 180 μs/step
   constant in both mooncake_both and mooncake_both_drfix. Caused
   by two `run_coroutine_threadsafe(...).result()` blocking waits
   in `kv_both` mode even when both queues are empty.
