mirror of
https://github.com/daijro/camoufox.git
synced 2026-10-03 16:00:19 +00:00
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) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1ee2dd31e1
commit
77edaebbae
@@ -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]:
|
||||
|
||||
Reference in New Issue
Block a user