Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 17 Aug 01:39
· 345 commits to main since this release
aef610b

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
helm 17.4s 1.3s 13×
k9s 14.3s 2.1s
caddy 8.7s 0.91s 10×
containerd 4.1s 0.40s 10×
gin 3.9s 0.37s 11×
cobra 1.4s 0.22s

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 1 kept 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