Skip to content

Performance: resources

Level: 301 · where the lessons of this chapter came from, and what to read next

One line: The primary sources are the testing package's documentation, the compiler's own source for its budgets and messages, and the Go blog's posts on b.Loop, profiling and PGO; the books cover benchmarking and profiling in their testing chapters; and a good deal of older advice about benchmark loops and inlining no longer describes Go 1.25.

Primary sources

Books

  • Alan Donovan and Brian Kernighan, The Go Programming Language (Addison-Wesley, 2015), chapter 11, "Testing" — 11.4, "Benchmark Functions" (the b.N loop of its day, -benchmem, and why absolute times mislead) and 11.5, "Profiling" (-cpuprofile, -memprofile, -blockprofile and go tool pprof).
  • Jon Bodner, Learning Go, 2nd ed. (O'Reilly, 2024), chapter 15, "Writing Tests" — "Using Benchmarks", with the box "Profiling Your Go Code"; chapter 6, "Pointers" — "Reducing the Garbage Collector's Workload" and "Tuning the Garbage Collector".
  • Go in Practice, 2nd ed. (Manning, 2025), chapter 6, "Formatting, testing, debugging, and benchmarking" — 6.4, "Benchmarking and performance tuning".
  • Adam Freeman, Pro Go (Apress, 2022), chapter 31, "Unit Testing, Benchmarking, and Logging" — "Benchmarking Code" and "Removing Setup from the Benchmark" (ResetTimer, StopTimer, StartTimer, which b.Loop now handles for the common case).
  • Miki Tebeka, Effective Go Recipes (Pragmatic, 2024), Recipe 33, "Calculating Cumulative Sum" — a benchmark, its allocations, and a CPU profile read with top; Recipe 56, "Using sync/atomic for a Faster Now" — a benchmark deciding between two designs; Recipe 75, "Using Build Tags for Conditional Builds" — net/http/pprof behind a build tag.

Not on the shelf

Talks and videos

Read with care

  • Benchmark tutorials written before Go 1.24, with for i := 0; i < b.N; i++. The loop still works, but it runs the benchmark function several times, times whatever setup sits above it on every round, and does nothing to stop the compiler discarding an unused result — allocs/op is a key, ns/op is not.
  • "Functions with loops cannot be inlined." True before Go 1.16 for for loops and before 1.18 for range loops; the lesson The compiler says what it inlines shows sumTo inlined with its loop.
  • Tables of ns/op quoted as facts. Every such number is one machine on one day; without the machine, the Go version and the number of runs, it cannot be compared with anything.
  • "fmt.Sprintf allocates N times." The count depends on whether the arguments are constants, small integers or run-time values — AllocsPerRun counts allocations shows 1 and 2 for the same format string.
  • Advice to remove bounds checks with unsafe. The prove pass removes the common shapes by itself, and a benchmark is the only way to know whether the remaining checks cost anything — Bounds checks, and how to drop them.

Checked 2026-09-23.