Repository navigation
feat(ci): diff wire size against the merge base and comment it on the PR - #289
Merged
Merged
Conversation
Every performance number in this repo is absolute: a measurement against a constant somebody typed. perf-budget.mjs's own baseline history records what that costs. The 129.23 KiB worker baseline sat 58% stale for months while the advisory fired on every single run and CI printed "hard checks green" over it. The 204.24 KiB replacement, set on 2026-08-04 after a direct measurement, was already over its alert four days later (258.34 KiB at 295ee97). A constant is not wrong because someone chose it badly. It is wrong because it describes a moment and the bundle does not hold still. So add the differential half, modelled on how astral-sh/ruff runs its memory and ecosystem jobs: build the merge base, build HEAD, measure both, post the delta, gate on nothing. - scripts/perf-snapshot.mjs records the built tree's wire sizes (client assets, 46 pages, the /a/ immutable tier, worker bundle gzip, per-module esbuild attribution, dictionary-delta coverage) and diffs two recordings into markdown. One dry-run self-builds, so a snapshot costs ~12s. - .github/workflows/perf-diff.yml runs it per PR and updates one marker-keyed comment. It is deliberately NOT part of `validate`: `validate` is the one required check on main, and a perf number that blocks a merge teaches people to widen the threshold rather than to read it. Two things the measurement had to get right. Both sides are measured with HEAD's copy of the script, stashed outside the tree before the first git switch, because the base does not have it on the PR that adds it and measuring each side with its own copy would report a change to the measurement as a change in wire size. And the noise floor is asymmetric: pages get 128 bytes, assets get none. A page carries /a/<name>.<hash8>.<ext> references, so touching one shared asset flips its hash and moves every page a few bytes (measured: a one-line nav.js edit moved 38 of 46 pages, max 41 bytes, net -0.03 KiB); an asset's bytes are its own content, so every byte of movement is signal. One floor everywhere would have hidden the 50-byte nav.js change that caused the churn. Sub-floor movers collapse into a counted line and stay in the totals. Nothing sampled is recorded. `wrangler check startup` read 9.6, 7.6, 6.4 and now 16.4 ms across identical bytes, and diffing two draws from a 2.6x spread manufactures findings in a comment whose credibility rests on every row being real. That check is reframed here from "regression tripwire" to diagnostic; the tripwire is the deterministic bundle gzip and module attribution beside it. The worker advisory is left firing rather than re-baselined. Re-baselining an unattributed 54 KiB is indistinguishable from silencing the check, and the diff is the thing that can now name which PR spent it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
aadhar-sh | 00d7579 | Aug 08 2026, 08:19 PM |
Contributor
Wire-size diff vs merge base
Brotli q11, the quality the edge serves. Every number here is deterministic: Client assetsNo change. 11 files, 57.99 KiB Brotli total. PagesNo change. 46 files, 465.79 KiB Brotli total. Worker bundleNo change. 261.74 KiB gzip. Dictionary deltas (
|
oddharsh
added a commit
that referenced
this pull request
Aug 8, 2026
#294) #289 and #293 shipped and ramped to 100% without a changelog entry, so /updates and /restore still name v178 as the newest build. This stages the entry that describes them. Nothing here reaches D1. bump-version.sh writes the projection only, and `deploy:promote` records the row once traffic actually reaches 100% — which is why the log is a follow-up commit rather than part of the work it describes. Co-authored-by: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Every performance number in this repo is absolute: a measurement against a constant somebody typed.
perf-budget.mjs's own baseline history is the receipt for what that costs.295ee97)Four days from a fresh baseline to a firing advisory. A constant isn't wrong because someone chose it badly; it's wrong because it describes a moment and the bundle doesn't hold still. And "258.34 against 255.30" says nothing about which PR spent the 54 KiB.
The change
The differential half, modelled on how
astral-sh/ruffruns its memory and ecosystem jobs: build the merge base, build HEAD, measure both, post the delta, gate on nothing.scripts/perf-snapshot.mjsrecords the built tree's wire sizes (11 client assets, 46 pages, the/a/immutable tier, worker bundle gzip, per-module esbuild attribution, dictionary-delta coverage) and diffs two recordings into markdown. Onewrangler deploy --dry-runself-builds, so a snapshot costs ~12s..github/workflows/perf-diff.ymlruns it per PR and updates one marker-keyed comment, matching the pattern already independabot-site-review.yml.It is deliberately not part of
validate.validateis the one required check onmain, and a perf number that blocks a merge teaches people to widen the threshold rather than to read it.What the report looks like
A tooling-only PR (this one):
That silence is the feature. A report that always has content stops being read.
A one-line
nav.jsedit:Three design decisions worth reviewing
Both sides are measured with HEAD's copy of the script, stashed in
$RUNNER_TEMPbefore the firstgit switch. The base doesn't have the script on the PR that adds it, and measuring each side with its own copy would report a change to the measurement as a change in wire size.The noise floor is asymmetric: pages get 128 bytes, client assets get none. A page carries
/a/<name>.<hash8>.<ext>references, so touching one shared asset flips its hash and moves every page's compressed size (measured: 38 of 46 pages, max 41 bytes, net -0.03 KiB). An asset's bytes are its own content, so nothing but editing it can move them and every byte is signal. One floor everywhere would have hidden the 50-bytenav.jschange that caused the churn. Sub-floor movers collapse into a counted aggregate line and stay in every total.Nothing sampled is recorded.
wrangler check startupread 9.6, 7.6, 6.4 and now 16.4 ms across identical bytes, a 2.6x spread. Diffing two draws from that manufactures findings in a comment whose credibility rests on every row being real. That check is reframed from "regression tripwire" to diagnostic; the tripwire is the deterministic bundle gzip and module attribution next to it. Same instinct as CodSpeed counting simulated instructions and ty's memory job pinningTY_MAX_PARALLELISM=1— remove the noise source rather than widen a threshold around it.Deliberately not done
The worker advisory is left firing rather than re-baselined. Re-baselining an unattributed 54 KiB is indistinguishable from silencing the check, and the diff is the thing that can now name which PR spent it. The observation is recorded in the baseline history instead.
Verification
Run locally against
origin/main:npm test— 179 passnpm run perf-budget— hard checks green (1 advisory, the pre-existing bundle one)npm run typecheck,npm run check-wrangler,npm run pages:check— cleanorigin/main, recorded this branch, diffed — silent, as it should be for a tooling-only changenav.jsedit produces the table above, then reverted🤖 Generated with Claude Code