perf-timeline: opt-in test262.total macro point - #16
Conversation
Fold the Test262 macro (the cmd/bench-test262 tooling from #10) into the timeline as a test262.total series, gated on a [perf-test262] commit marker (or workflow_dispatch) so it adds ~4 min only when opted in. Anchor-normalized like bench-ratchet; non-fatal so it never drops the micro snapshot. Pairs with the page series + CPU filter in #15. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
[P1] Keep the measured Test262 set stable across snapshots The workflow records test262.total by summing only the tests that pass in that particular run. That means the measured corpus changes whenever correctness changes: fixing tests adds their runtime and can look like a performance regression, while newly failing tests disappear from the sum and can look like a speedup. Recording the passing count provides useful provenance, but it does not make the points comparable. Please use a fixed benchmark allowlist, or retain enough per-test timing data for the page to compare a common intersection across snapshots. At minimum, points with different contributing sets should not be presented as one continuous performance series. The workflow otherwise passes actionlint; I did not run the full Test262 macro. |
|
Tracked in #26, which consolidates this into a standalone issue (survives this PR closing) and adds the |
nooga
left a comment
There was a problem hiding this comment.
Overview
This adds one gated step-pair to .github/workflows/perf-timeline.yml: a test262 corpus cache and a step that runs scripts/macro-test262.sh, extracts the total record's ns_per_op/iterations, anchor-normalizes it, and splices it into the snapshot JSON as benchmarks["test262.total"] before publish.
Opt-in gating
Correctly implemented: both new steps share the same gating condition, so ungated pushes see zero behavior change, and continue-on-error: true correctly isolates a macro/jq failure from the primary snapshot.
One nit: workflow_dispatch unconditionally runs the macro, even though the file's existing comment describes workflow_dispatch as a backfill mechanism for historical micro snapshots. Every manual backfill dispatch now silently costs an extra ~4 minutes with no opt-out. Consider a workflow_dispatch boolean input (default false) instead.
test262.total comparability vs. #24
This is the substantive issue. #24 ("fingerprint the contributing test set so test262.total is comparable") explicitly states that #16 should gate its test262.total series on set_hash — #24 provides the tool, the page-side drop/flag is #16's job. Since #24 isn't merged yet and this PR doesn't reference it, merging #16 as-is emits unfingerprinted test262.total points onto the durable append-only timeline that will need special-casing (or discarding) once #24 lands.
Recommend either:
- Sequencing #24 before #16 and threading
set_hashthrough this step'sjqsplice, or - Landing #16 now but adding an explicit code comment/TODO referencing #24, so pre-fingerprint points are recognizably legacy/lower-confidence rather than silently indistinguishable later.
Minor
jq -s '.[] | select(...) | .ns_per_op'slurps the whole file into an array only to re-stream it —jq 'select(.name=="total") | .ns_per_op'(no-s) is equivalent and simpler for JSONL input.- No test coverage added (understandable for a CI-workflow change), but worth a manual
workflow_dispatchdry run before merge to confirm thejqsplice against a real snapshot shape.
The summed metric conflated per-test speed with how many tests pass, so a conformance win (more passing tests add their durations) read as a perf regression on the timeline (nooga#26). Fold the mean (summed_ns / passing_count) instead, which removes the count-inflation, and carry the contributing set's set_hash (from bench-test262, nooga#24) onto the snapshot entry so a residual composition shift the mean can't cancel stays visible to the page. Guards the empty passing set (skip the fold; mean is undefined). set_hash is soft: absent until nooga#24 lands, in which case the entry simply omits it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed the review:
Validated end-to-end via a |
nooga
left a comment
There was a problem hiding this comment.
Thanks Matt — nice touch making this opt-in and continue-on-error, and switching to mean (vs sum) so the metric can't conflate conformance gains with perf regressions. Merging.
test262.total is a mean over the passing set (perf-timeline #16), whose membership drifts as conformance changes. Where a point's set_hash differs from its predecessor the mean isn't over the same workload, so the slope across that gap isn't a pure engine delta (#26, the #23 segmentation follow-on). Dash the connecting span, mark the changed point with a triangle, add a tooltip + count note — so a composition jump reads differently from a real engine move. Also fixes the ?mode= param regression from the tab rename: match case-insensitively so old ?mode=all / ?mode=overall links still resolve. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pairs with #15 (touches a different file, so it can land in either order). Wires the Test262 macro-benchmark (the
cmd/bench-test262tooling merged in #10) into the timeline, so an opted-in commit records a whole-suite point on the trend page.Relationship to #10
#10 added the
perf-test262label, which runs an A/B on a PR (merge-base versus head) and comments the delta, a pre-merge "did this change move perf?" check. This is the complementary post-merge half: a single anchor-normalizedtest262.totalpoint on the trend page. Same intent — run the test262 macro here — over two surfaces: a label on a PR, a marker in a commit.Opt-in by design
The macro adds ~4 minutes to a snapshot, so it doesn't run on every push — only when the commit message contains
[perf-test262], or viaworkflow_dispatch(with a boolean toggle so a manual backfill can skip the extra ~4 min). Without the marker the timeline is unchanged. The trade-off is a sparse, dotted trend rather than a continuous one: points appear where you ask for them.How it works
On an opted-in commit, after the usual snapshot it runs the macro (built-ins and language, sharded so memory stays bounded), then injects a
test262.totalentry. The metric is the mean per-test execution time over the passing, non-timed-out tests (summed_ns / passing_count), anchor-normalized like every other series and tagged with the run'sset_hash(frombench-test262, #24). The step is non-fatal, so a macro hiccup never drops the micro snapshot. The page (#15) renders it as its own self-relative, segmented series.Metric: mean, not sum (updated after review)
The first version injected the summed per-test time. Summing conflates per-test speed with how many tests pass: a conformance win (more passing tests add their durations) reads as a slowdown on the trend (#26). The mean removes that count-inflation, and the
set_hashtag carries the exact contributing set so a residual composition shift the mean can't cancel stays visible to the page.set_hashis soft — absent until #24 lands, in which case the entry simply omits it. A fixed-reference-set is the deeper follow-up tracked in #26; this is the near-term mitigation.