From 054746c76028314d5a15c108b0aaa9f9e9ae07ec Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Mon, 15 Jun 2026 18:08:54 +0000 Subject: [PATCH] bench(lbug): add absolute large-scale wall-time backstop to the emit gate (#2215 review) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scaling-ratio gate only compares large/small, so a uniform Nx slowdown at both scales passes with ratio ~1.0. Add an opt-in max_ms_large ceiling (1000ms vs observed ~200ms — generous, host-noise-tolerant) that --check enforces alongside the ratio, catching a gross absolute regression the ratio misses. Co-Authored-By: Claude Opus 4.8 (1M context) --- gitnexus/bench/emit-persistence/baselines.json | 3 ++- gitnexus/bench/emit-persistence/measure.mjs | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gitnexus/bench/emit-persistence/baselines.json b/gitnexus/bench/emit-persistence/baselines.json index 0bb4250c3..93806b252 100644 --- a/gitnexus/bench/emit-persistence/baselines.json +++ b/gitnexus/bench/emit-persistence/baselines.json @@ -1,5 +1,6 @@ { "fingerprint": "1b9dd0b783899b47067c36511d241860f291ac736e57682b0ece14148e3958ff", "scaling_budget": 1.8, - "_note": "fingerprint = sha256 over per-file digests (filename + sha256(file bytes)), entry list sorted — binds each emitted line to its file so a row routed to the WRONG pair file changes the hash, AND catches within-file row reordering (file bytes hashed as-written). Byte-identity gate for #2203 U2/U3. NOTE: a future change that legitimately reorders emit (without changing the node/edge SET) will trip --check; regenerate then. scaling_budget bounds (t_large/t_small)/(LARGE/SMALL): observed ~0.95-1.05 (linear); 1.8 tolerates disk-I/O timing noise on CI while still catching an O(n^2) re-regression (~4x). Regenerate via `node --import tsx bench/emit-persistence/measure.mjs`." + "max_ms_large": 1000, + "_note": "fingerprint = sha256 over per-file digests (filename + sha256(file bytes)), entry list sorted — binds each emitted line to its file so a row routed to the WRONG pair file changes the hash, AND catches within-file row reordering (file bytes hashed as-written). Byte-identity gate for #2203 U2/U3. NOTE: a future change that legitimately reorders emit (without changing the node/edge SET) will trip --check; regenerate then. scaling_budget bounds (t_large/t_small)/(LARGE/SMALL): observed ~0.95-1.05 (linear); 1.8 tolerates disk-I/O timing noise on CI while still catching an O(n^2) re-regression (~4x). max_ms_large=1000ms is a coarse absolute backstop (observed ~200ms) that catches a gross uniform slowdown the ratio gate misses; generous so CI host noise won't flake it. Regenerate via `node --import tsx bench/emit-persistence/measure.mjs`." } diff --git a/gitnexus/bench/emit-persistence/measure.mjs b/gitnexus/bench/emit-persistence/measure.mjs index 49fbe278c..f7623bc34 100644 --- a/gitnexus/bench/emit-persistence/measure.mjs +++ b/gitnexus/bench/emit-persistence/measure.mjs @@ -198,6 +198,15 @@ if (!CHECK) { `(${SMALL}->${LARGE} entities, ms ${result.elapsed_ms_small}->${result.elapsed_ms_large})`, ); } + // Absolute backstop: the scaling ratio alone passes a uniform Nx slowdown (it + // only compares large/small). A generous, host-noise-tolerant ceiling catches + // a gross absolute regression. Opt-in (only enforced when max_ms_large is set). + if (base.max_ms_large !== undefined && result.elapsed_ms_large >= base.max_ms_large) { + failures.push( + `absolute wall-time regression: elapsed_ms_large ${result.elapsed_ms_large}ms >= budget ` + + `${base.max_ms_large}ms (coarse backstop, not a tight SLA)`, + ); + } process.stdout.write(JSON.stringify(result) + '\n'); if (failures.length > 0) { for (const f of failures) process.stderr.write(`[emit-persistence --check] FAIL: ${f}\n`);