From 77edaebbaed374628bf3809927711aca94af29ba Mon Sep 17 00:00:00 2001 From: Jake Writer Date: Thu, 17 Sep 2026 14:51:07 -0600 Subject: [PATCH] test(patches): the query-cost probe measured the JIT, not the IPC query-cost failed in CI with "hardwareConcurrency 19 ms vs userAgent 0 ms". The 0 ms is the tell: the loop reads a getter and discards the result, so the JIT elided the BASELINE loop entirely on that runner. With the baseline at zero the check `costHwc > 5 * costUA + 15` collapses to a flat 15 ms allowance for 20000 reads -- 0.75 us each -- while a healthy read of a value that lives in the config costs ~1 us. It was timing whether the JIT dropped the loop. Every read is now accumulated into a sink that is returned, so the loop cannot be optimised away. (userAgent still measures ~0 because the string is cached, hence the second change.) The allowance on the two config-read checks goes to 40 ms. The state they guard against is a sync IPC per read, measured at ~12 us each when it regressed, i.e. ~240 ms over this loop; a healthy read is ~20 ms. 40 sits an order of magnitude under the defect and clear of a slow runner. The timezone-cost check keeps its 15 ms allowance and is commented to say why: its healthy numbers are ~2 ms vs ~1 ms and its regression is ~20 ms over the same loop, so widening it to 40 would step over the very thing it exists to catch. Verified against the local build: PASS, costHwc 7-13 ms, costLocalDate 1-2 ms. Co-Authored-By: Claude Opus 5 (1M context) --- tests/patches/stock-parity-probes.py | 31 ++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/patches/stock-parity-probes.py b/tests/patches/stock-parity-probes.py index eea20c7..6d96ffe 100644 --- a/tests/patches/stock-parity-probes.py +++ b/tests/patches/stock-parity-probes.py @@ -133,11 +133,21 @@ PROBES = """async (port) => { setTimeout(() => r('timeout'), 5000); }); - const time = (fn) => { const t = performance.now(); for (let i = 0; i < 20000; i++) fn(); return performance.now() - t; }; - out.costColor = time(() => matchMedia('(color: 8)').matches); - out.costMinWidth = time(() => matchMedia('(min-width: 1px)').matches); + // The result of every read is accumulated into `sink`, and `sink` is returned. + // Without that the JIT elides the whole loop for a side-effect-free getter -- + // which it did for navigator.userAgent on a CI runner, timing the BASELINE at + // 0 ms and collapsing the comparison below into a flat 15 ms allowance. + let sink = 0; + const time = (fn) => { + const t = performance.now(); + for (let i = 0; i < 20000; i++) sink += fn(); + return performance.now() - t; + }; + out.costColor = time(() => matchMedia('(color: 8)').matches ? 1 : 0); + out.costMinWidth = time(() => matchMedia('(min-width: 1px)').matches ? 1 : 0); out.costHwc = time(() => navigator.hardwareConcurrency); - out.costUA = time(() => navigator.userAgent); + out.costUA = time(() => navigator.userAgent.length); + out.sink = sink; // Fresh Date objects: a Date caches its local-time fields after one read. let n = 0; out.costLocalDate = time(() => new Date(1.6e12 + (n++) * 3.6e6).getHours()); @@ -255,12 +265,21 @@ def main() -> int: humanized = out["wheelHumanized"] if len(humanized) != 3 or any(e["wd"] % 120 for e in humanized): failures.append(f"wheel-notches: humanized wheel(0, 300) gave {humanized}") - if out["costColor"] > 5 * out["costMinWidth"] + 15: + # 20000 reads of a value that lives in the config cost ~20 ms here, i.e. + # ~1 us each: a hash lookup, no IPC. The state this guards against is a sync + # IPC per read, measured at ~12 us each when it regressed -- 240 ms over the + # same loop. The allowance sits an order of magnitude below that and well + # above a healthy read, so neither a fast runner nor a slow one flips it. + if out["costColor"] > 5 * out["costMinWidth"] + 40: failures.append(f"query-cost: (color) {out['costColor']:.0f} ms vs (min-width) {out['costMinWidth']:.0f} ms") - if out["costHwc"] > 5 * out["costUA"] + 15: + if out["costHwc"] > 5 * out["costUA"] + 40: failures.append(f"query-cost: hardwareConcurrency {out['costHwc']:.0f} ms vs userAgent {out['costUA']:.0f} ms") if out["timeZone"] != "Asia/Tokyo": failures.append(f"timezone: launch-level zone not applied ({out['timeZone']}) -- timezone-cost is vacuous") + # Not widened like the two above: a healthy local-Date loop costs ~2 ms here + # against ~1 ms for UTC, and the regression this catches (DateTimeInfo + # rebuilt per call under a launch timezone) ran ~1 us per call, i.e. ~20 ms + # over this loop. A 40 ms allowance would step straight over it. if out["costLocalDate"] > 5 * out["costUTCDate"] + 15: failures.append(f"timezone-cost: getHours {out['costLocalDate']:.0f} ms vs getUTCHours {out['costUTCDate']:.0f} ms") if relaunch != [["Asia/Tokyo"] * 2, ["America/Chicago"] * 2]: