chore(ci): Stabilize Advisory Benchmark Comparisons - #4561
Conversation
🟡 Heimdall Review Status
|
| @staticmethod | ||
| def paired_deltas(base: Measurement, head: Measurement) -> list[float]: | ||
| """Return nearby head/base percentage deltas in baseline argument order.""" | ||
| return [ | ||
| (head_median / base_median - 1.0) * 100 | ||
| for base_median, head_median in zip( | ||
| base.repeat_medians, head.repeat_medians, strict=False | ||
| ) | ||
| ] |
There was a problem hiding this comment.
Nit: paired_deltas is only called after is_significant gates on has_all_repetitions, so in practice both tuples are the same length. But the method itself doesn't enforce that precondition — strict=False silently truncates to the shorter side. If a future caller invokes paired_deltas without the is_significant gate, the mismatch is swallowed and the len(deltas) == self.expected_repetitions check in is_regression/is_improvement silently returns False rather than surfacing the bug.
Consider either using strict=True (to fail loudly on mismatched repetitions) or adding an assert, so a broken call site can't produce a silently-wrong result:
for base_median, head_median in zip(
base.repeat_medians, head.repeat_medians, strict=True
)| if b in base and b in head and not self.has_all_repetitions(base[b], head[b]) | ||
| ] | ||
|
|
||
| if not (regressed or improved or dropped or incomplete): |
There was a problem hiding this comment.
The early-return path on line 304 checks regressed or improved or dropped or incomplete, but incomplete only contains benchmarks that failed has_all_repetitions. A benchmark with complete repetitions but unstable repeats (has_stable_repetitions returns False) would be flagged as is_notable (line 196) but doesn't appear in any of the four lists checked here. The early return fires and the unstable benchmark's row is never rendered — despite is_notable wanting to surface it.
Consider adding an unstable list (analogous to incomplete) and including it in this guard:
unstable = [
b
for b in bench_ids
if b in base and b in head
and self.has_all_repetitions(base[b], head[b])
and not self.has_stable_repetitions(base[b], head[b])
]
...
if not (regressed or improved or dropped or incomplete or unstable):Amp-Thread-ID: https://ampcode.com/threads/T-01a01fda-4fad-70ea-8cd6-8f493a177180 Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a01fda-4fad-70ea-8cd6-8f493a177180 Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a01fda-4fad-70ea-8cd6-8f493a177180 Co-authored-by: Amp <amp@ampcode.com>
2f1efdd to
0e24648
Compare
Amp-Thread-ID: https://ampcode.com/threads/T-01a01fda-4fad-70ea-8cd6-8f493a177180 Co-authored-by: Amp <amp@ampcode.com>
Review SummaryCI-only changes to stabilize advisory benchmarks (ABBA ordering, prebuilt binaries, CPU pinning, geometric-mean aggregation) plus a benchmark relocation from FindingsTwo inline comments were posted on
Notes
|
|
Caution This PR may regress performance. 1 benchmark(s) slower by more than 10% beyond the noise band: Benchmark results (advisory)Geometric-mean time from two base-head-head-base (ABBA) runs on one pinned CPU. A wall-clock change is only flagged when both paired comparisons clear the threshold in the same direction, the repeated-run confidence envelopes do not overlap, and each side's same-code A/A spread is below 10%. Only notable or incomplete results are listed. This check never blocks a merge.
54 benchmark(s) within ±10% omitted. |
Summary
Runs base and head benchmarks in an interleaved ABBA sequence using prebuilt binaries pinned to one CPU, reducing drift without adding an external benchmarking service. Aggregates paired Criterion runs with geometric means and repeat-spread checks so noisy or inconsistent results are reported without producing performance claims. Keeps the existing advisory threshold and PR comment workflow.