You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
const footer = `<sub>Same-runner A/B (sharded ${process.env.SHARD_TOTAL || ''}-way): main (\`${baseSha}\`) and this PR were built and benchmarked back-to-back on the same runner per shard, so hardware variance cancels out. ⚠️ = PR mean ≥ +${thresholdPct}% slower than main and beyond combined std-dev; ✅ = correspondingly faster.</sub>`;
421
-
422
-
const header = ['| Benchmark | This PR | StdDev | main | Δ |', '|---|---:|---:|---:|---:|'];
Copy file name to clipboardExpand all lines: CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -26,12 +26,15 @@ All notable changes to Celerity are documented here. This project follows [Keep
26
26
- A "Documentation links" section in `CONTRIBUTING.md` covering the slug rule and how to look an anchor up rather than guess it. Closes [#339](https://github.com/marius-bughiu/Celerity/issues/339).
27
27
-`scripts/benchmark_relevant_changes.js` — a CI gate that skips the sharded benchmark run on a pull request whose diff cannot move a measured number: documentation, the test / fuzz / AOT-smoke projects, or comments inside `.cs` files. It skips only what it can prove inert and never applies to `main`. Closes [#335](https://github.com/marius-bughiu/Celerity/issues/335).
28
28
- A `--shard-dry-run` switch on the benchmarks runner that resolves a shard's class list without measuring anything. Closes [#300](https://github.com/marius-bughiu/Celerity/issues/300).
29
+
-`scripts/benchmark_comment.js` — the pull-request benchmark comment, moved out of `benchmarks.yml` so the rule deciding which rows count as a regression is runnable and testable, with a `--self-test` wired into `ci.yml`. Closes [#351](https://github.com/marius-bughiu/Celerity/issues/351).
30
+
- That comment now publishes the run's own **measured noise floor** — the p50, p90 and p95 of |Δ| across every paired row, of which any one pull request changes only a handful — so a flag can be read against the drift it arrived in instead of an assumed one. Closes [#351](https://github.com/marius-bughiu/Celerity/issues/351).
29
31
30
32
### Fixed
31
33
32
34
- Pushing to a pull request now supersedes that PR's in-flight benchmark run instead of stacking another eight-runner matrix behind it, so `CI` and `Coverage` no longer queue behind superseded perf runs. Pushes to `main` are keyed per commit and never cancelled. Closes [#319](https://github.com/marius-bughiu/Celerity/issues/319).
33
35
- A benchmark shard no longer times out on a pull request that adds a benchmark class: the `main` base now replays the class list the PR head resolved, so shard *i* is the same slice on both sides. The job budget was also resized to the measured slices, which the suite had outgrown. Closes [#300](https://github.com/marius-bughiu/Celerity/issues/300).
34
36
- A benchmark comparison that is missing a shard now says so in the PR comment, instead of reading exactly like a complete run. Closes [#300](https://github.com/marius-bughiu/Celerity/issues/300).
37
+
- The PR benchmark comment no longer cries wolf: its noise guard is now a **3σ** bar over the two measurements' combined standard deviation, added in quadrature, rather than a 1σ sum. Replayed over a run whose library IL was byte-identical to `main`, that cuts flagged rows from **13 to 2** while detecting the same regressions on every benchmark precise enough to resolve one. Closes [#351](https://github.com/marius-bughiu/Celerity/issues/351).
35
38
36
39
-`PartialSort.TopK` now throws `ArgumentException` when its `destination` overlaps its `source`, instead of silently returning a wrong answer and writing to the source it documents as untouched. Disjoint slices of one array are still accepted, matching `RadixSort` and `CountingSort`.
37
40
- Corrected `RadixSort.ArgSort` XML documentation: only its `ReadOnlySpan<int>` overload rejects `indices` that shares storage with `keys`. Documentation only.
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,14 +82,15 @@ dotnet run -c Release -- --filter '*' # run everything with the default (slow, h
82
82
83
83
Results are parsed by [`benchmark-action/github-action-benchmark`](https://github.com/benchmark-action/github-action-benchmark) and:
84
84
85
-
-**On a PR**: a comment is posted with the same-runner A/B comparison vs `main`. Rows that move by more than ±10% *and*beyond the combined standard deviation of both measurements are flagged; the flags are advisory, so a noisy row does not fail the job. If any shard failed to report, the comment says so above the fold — a partial comparison is otherwise indistinguishable from a clean one.
85
+
-**On a PR**: a comment is posted with the same-runner A/B comparison vs `main`. A row is flagged when it moves past ±10% *and* the gap exceeds **3σ** of the two measurements' combined standard deviation (added in quadrature); the flags are advisory, so a noisy row does not fail the job. The comment also publishes that run's **measured noise floor** — the p50, p90 and p95 of |Δ| across every paired row, of which any one PR changes only a handful — so a flag can be read against the drift it arrived in rather than against an assumed one. If any shard failed to report, the comment says so above the fold — a partial comparison is otherwise indistinguishable from a clean one.
86
86
-**On a push to `main`**: the new measurement is appended to the `gh-pages`-stored history powering the dashboard at <https://marius-bughiu.github.io/Celerity/dev/bench/>.
87
87
88
88
Three things about the run are worth knowing before you wonder why it did or did not happen:
89
89
90
90
-**It supersedes itself.** Pushing to a PR cancels that PR's in-flight benchmark run rather than stacking another eight-runner matrix behind it; only the newest numbers are ever read. Pushes to `main` are keyed per commit instead, so none is ever cancelled and the published history has no gaps.
91
91
-**It is skipped when the diff cannot move a number.**[`scripts/benchmark_relevant_changes.js`](scripts/benchmark_relevant_changes.js) gates the PR path: a diff that touches only documentation, only the test / fuzz / AOT-smoke projects, or only comments inside `.cs` files does not buy a three-hour A/B run. The gate is one-directional — anything it cannot prove inert (an added or deleted file, a `.csproj`, a git command that fails) runs the suite — and it never applies to `main`, so a wrongly-skipped PR is still measured on merge. Run it yourself with `node scripts/benchmark_relevant_changes.js <base> <head>`.
92
92
-**Shard *i* means the same slice on both sides.** The base run replays the class list the head resolved instead of packing its own. Shard membership comes from bin-packing over the benchmark class list, so a PR that *adds* a benchmark class would otherwise pack the two sides differently and could pair a light head slice with a heavy base one.
93
+
-**A flag is evidence, not a verdict.** Even at 3σ, two rows in a ~750-row run still flagged on a diff whose IL was byte-identical to `main`: a case whose two builds land in different code or data layouts shifts by tens of percent with a tight spread on both sides, and nothing inside a single A/B pass separates that from a real change. Re-run before acting on a flag near the run's published p95. The rule lives in [`scripts/benchmark_comment.js`](scripts/benchmark_comment.js), which documents how the 3σ bar was calibrated; `node scripts/benchmark_comment.js --self-test` pins it against the measurements it was chosen against.
93
94
94
95
If a change is motivated by performance, include before/after numbers from a local Release run in the PR description — the CI job is a guardrail, not a precision instrument. Numbers without `-c Release` are not useful — BenchmarkDotNet refuses to run in Debug.
0 commit comments