v0.5.0
A performance release. Same linters, same findings, same config — less time and a third less memory.
Faster and lighter
Measured on prometheus ./... (Darwin arm64, 10 core), v0.4.1 → v0.5.0:
| v0.4.1 | v0.5.0 | ||
|---|---|---|---|
| cold wall | 2.33s | 1.98s | −15% |
| warm wall (one file changed) | 1.51s | 1.36s | −10% |
| peak memory | 2517 MiB | 1717 MiB | −32% |
-j 1 wall |
5.48s | 4.90s | −11% |
Most of it came from one thing. Three enums that sit in million-element arrays were each sized by one or two oversized variants — a Rust enum costs what its largest variant costs, so a 24-byte expression was paying for a 192-byte one:
| before | after | |
|---|---|---|
Expr |
192 B | 80 B |
Stmt |
656 B | 320 B |
TypeData |
112 B | 72 B |
ObjectData |
104 B | 64 B |
Boxing the outliers took every AST node, type and object in the process down with them. Details and the measurements that sized each one: docs/PERF_TASKS_V9.md.
vs golangci-lint
Real repositories, their own .golangci.yml, cold cache, golangci-lint 2.12.2:
| Repository | golangci-lint | guff | Speedup |
|---|---|---|---|
| grafana | 290.4s | 17.8s | 16× |
| consul | 39.4s | 4.7s | 8× |
| helm | 17.4s | 1.3s | 13× |
| k9s | 14.3s | 2.1s | 7× |
| caddy | 8.7s | 0.91s | 10× |
| containerd | 4.1s | 0.40s | 10× |
| gin | 3.9s | 0.37s | 11× |
| cobra | 1.4s | 0.22s | 6× |
Reproduce with ./benchmarks/run.sh --oss --tier pr,nightly. Full detail: SCOREBOARD.md.
grafana's golangci-lint number is 290.4s here against 394.8s in the v0.4.1 README, so the ratio reads 16× where it used to read 17× — a different checkout, a different golangci-lint, a different day. Both sides of every row are this run's measurements.
No behaviour changes
Findings are byte-identical to v0.4.1 across the regression corpus, at -j 1 and -j N, with node-kind masks on and off. 114/114 golangci-lint v2 linters, compat golden 81/81, 3119 tests.
Also in this release
Claude Code is now called out alongside Cursor in the agent docs — put the lint block in CLAUDE.md and it applies every session. See docs/AGENTS.md.
What's Changed
- Persist guff's analysis cache across CI runs by @dakimura in #1
- Halve the analyze phase: an inspector that skips the 97% it used to read, and a mutex ten workers queued on by @dakimura in #2
- The compat gate has never passed in CI: the runner's Go was two minors behind the baselines by @dakimura in #3
- Two fixtures were linux-only, so the golden never compared them by @dakimura in #6
- Comment linters were paying for object resolution none of them read by @dakimura in #5
- The shape ledger was a laptop measurement the runner could not reproduce by @dakimura in #4
- One question asked twenty-five times, and a speculation that had never once hit by @dakimura in #7
- Every package's results stayed alive until every other package caught up by @dakimura in #8
-j 1kept every package's results alive the way the wavefront used to by @dakimura in #9- Box the two Expr variants that were sizing every AST node (and finish PERF_TASKS_V8) by @dakimura in #10
- Box the two TypeData variants that were sizing every arena slot by @dakimura in #11
- Box the ObjectData variant that was sizing every object slot by @dakimura in #12
- Correct the round's closing numbers, measured on merged main by @dakimura in #13
- Re-lock both regress baselines on the round's numbers by @dakimura in #14
- Release 0.5.0: re-measure the OSS benchmarks and refresh the docs by @dakimura in #15
New Contributors
Full Changelog: v0.4.1...v0.5.0