Skip to content

feat(bench): --baseline to fail a run on a performance regression - #1073

Merged
Chemaclass merged 1 commit into
mainfrom
feat/1029-bench-baseline
Aug 12, 2026
Merged

Chemaclass merged 1 commit into
mainfrom
feat/1029-bench-baseline

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #1029

@max_ms is an absolute ceiling: loose enough to survive the slowest runner, so it only catches catastrophes and says nothing about the 30% slowdown that stays under it. Every performance campaign in this repo asked "is this slower than before" and answered it by hand.

💡 Changes

  • --baseline <file> compares the run against the [feat(bench): --report-json / --report-junit for benchmark results #1028] --report-json document of an earlier one, failing when a benchmark exceeds baseline × (1 + tolerance/100); --baseline-tolerance (default 10) and --baseline-update <file> complete the workflow.
  • Comparison uses the median, not the mean: one descheduled iteration on a shared runner moves the mean far more, and a gate that cries wolf gets disabled.
  • A benchmark the baseline does not know is new, one only in the baseline is removed — reported, never fatal. A missing or malformed baseline exits non-zero rather than quietly comparing against nothing.
  • Parsed with awk, not jq (optional elsewhere in bashunit — a gate that does nothing when a tool is missing is the bug this prevents), all arithmetic under LC_ALL=C (7 test failures on Bash 5.3 macOS (nix-shell) #912).

@max_ms is an absolute ceiling, and to survive the slowest CI runner it
has to be loose -- so it only catches catastrophes and says nothing
about the 30% slowdown that stays under it. Every performance campaign
in this repo (#761, #798, #830, #977) actually asked "is this slower
than before", and answering it meant comparing by hand.

--baseline compares against the --report-json document of an earlier run
(#1028), failing when a benchmark exceeds baseline * (1 + tolerance/100)
with a default tolerance of 10 percent. --baseline-update records the
new reference, and the table prints a per-benchmark delta so an
improvement is visible too.

The comparison uses the median, not the average: one descheduled
iteration on a shared runner moves the mean far more than the middle
value, and a gate that cries wolf gets disabled.

A benchmark the baseline does not know is reported as new, and one only
in the baseline as removed; neither fails, because the commit that
deletes a benchmark must not fail on its absence. A missing or malformed
baseline exits non-zero -- a gate quietly comparing against nothing
would report every run green, which is worse than no gate.

Parsed with awk, not jq: jq is optional everywhere else in bashunit, and
a gate that does nothing when a tool is missing is the bug this feature
exists to prevent. All arithmetic runs under LC_ALL=C (#912).

Binary size budget raised to 608 KiB.

Closes #1029
@Chemaclass Chemaclass added the enhancement New feature or request label Aug 12, 2026
@Chemaclass Chemaclass self-assigned this Aug 12, 2026
@Chemaclass Chemaclass added the enhancement New feature or request label Aug 12, 2026
@Chemaclass
Chemaclass merged commit 609a510 into main Aug 12, 2026
37 checks passed
@Chemaclass
Chemaclass deleted the feat/1029-bench-baseline branch August 12, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant