bench(signals): amortize projection-root-write over 20 commits per body - #3435
Conversation
Three benchmarks share one process and one set of 20k-key fixtures, and each body performed a single commit. V8 emits a one-off ~100k-instruction tier-up chunk that attaches to whichever frame is running when it fires and lands in exactly one of the three windows — at ~540k Ir per root write that is 16-20% of a window, and it moves between windows on unrelated changes. CodSpeed's bisection of #3431 (2026-09-14) made this exact: a change costing ~300 instructions on its own path read as -8.9% on the root write and x2.4 on the untouched nested write; a provably no-op extra call added to `next` read as -5.5% on the root write and +22% on the untouched store setter (537,655 → 508,044 and 513,411 → 627,428 Ir; every reactive-graph symbol bit-identical). Each body now runs COMMITS = 20 commits. The chunk amortizes to <1% of a window — below the 5% gate — and the three stay per-commit comparable, which is the parity this file guards (#3352 derive vs #3044 setter floor). Absolute numbers re-baseline ×20. Co-authored-by: Claude via Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
|
Coverage Report for CI Build 34892248743Coverage remained the same at 71.842%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will degrade performance by 61.38%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | projection derive: write one NESTED field (reference) |
523.8 µs | 2,525.2 µs | -79.26% |
| ❌ | projection derive: delete + set one ROOT key (#3352) |
455.3 µs | 1,309.3 µs | -65.22% |
| ❌ | createStore setter: delete + set one root key (#3044 overlay) |
436.8 µs | 547 µs | -20.14% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing bench/projection-root-write-amortize (2d2a190) with next (25c5064)1
Bench hygiene, no runtime change. Follow-up to the CodSpeed investigation on #3431.
Why
tests/store/projection-root-write.bench.tsruns three benchmarks in one process over one set of 20k-key fixtures, and each body performed one commit. V8 emits a one-off ~100k-instruction tier-up chunk that attaches to whichever JS frame is running when it fires, and it lands in exactly one of the three windows. At ~540k Ir per root write that is 16–20% of a window — and it moves between windows on unrelated changes.CodSpeed's bisection of #3431 (instruction counts, reproducible to ±2):
nextnext+ a provably no-op extra callEvery reactive-graph symbol in the window was bit-identical between base and head; the delta is the chunk relocating. The flame graph attributed it to
recomputeself-time via JIT code-range aliasing, which is why it looked like a real regression at first.Change
Each body runs
COMMITS = 20commits. The chunk amortizes to <1% of a window — under the 5% gate — and the three benchmarks stay per-commit comparable, which is the parity the file guards (#3352 derive vs #3044 setter floor). Absolute numbers re-baseline ×20 on the CodSpeed dashboard; the comment in the file records why.Locally (
vitest bench): ~39 µs / 20 commits for the root write, ~2 µs per commit — same per-commit floor as before.Co-authored-by: Claude via Cursor noreply@cursor.com