Master Go Benchmarks: Accurate Performance Testing and Advanced Tools
This article explains how to use Go's testing framework for benchmarks, ensure a stable environment, improve measurement accuracy with techniques like perflock and timer controls, and leverage tools such as benchstat, bench, and funcbench for deeper performance analysis.
When optimizing code performance, you first need a baseline measurement. Go's standard library testing framework provides benchmark capabilities. This article introduces how to run benchmarks, improve their accuracy, and presents two tools that simplify benchmarking.
Stable testing environment
Performance tests are heavily influenced by the environment, so maintain stability for reproducible results.
Keep the machine idle and avoid sharing hardware resources.
Disable power‑saving modes, especially on laptops.
Avoid virtual machines or cloud instances, as oversold CPU and memory cause instability.
Run each benchmark multiple times (e.g., 20 repetitions) to obtain statistically meaningful data.
How benchmarks work
A benchmark repeatedly calls a function and records execution time and other metrics. A typical benchmark function looks like this:
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-1) + fib(n-2)
}
func BenchmarkFib20(b *testing.B) {
for i := 0; i < b.N; i++ {
// Call the function we're benchmarking
fib(20)
}
}Benchmark functions must start with Benchmark. They can be run with:
go test -bench .
go test -bench="BenchmarkFib20"b.N
The b.N field in b *testing.B indicates how many times the benchmark loop should run. The testing tool starts with 1 and increases the count until the benchmark runs for roughly one second, using a sequence such as 1, 2, 3, 5, 10, 20, 30, 50, 100, etc.
Advanced parameters
count– controls the number of iterations, overriding b.N. benchtime – sets the total run time, defaulting to 1 second. benchmem – measures memory allocation counts. cpu – specifies how many CPU cores to use; the default is the number of logical CPUs. Additional go test flags such as cpuprofile, memprofile, and trace are also supported.
Improving accuracy
Reduce system noise: perflock
The perflock tool limits CPU clock frequency, reducing system interference and yielding more reliable benchmark results with lower variance.
ResetTimer
If setup work before the benchmark is time‑consuming, call b.ResetTimer() to exclude that overhead from the measurement.
StopTimer & StartTimer
Similarly, you can pause and resume timing around setup or teardown code using b.StopTimer() and b.StartTimer().
Measuring benchmarks
The official benchstat tool compares two benchmark runs and reports statistical differences.
Benchstat computes statistical summaries and A/B comparisons of Go benchmarks.
For example, comparing bubbleSort and quickSort:
func softNums() {
//bubbleSort(nums)
//quickSort(nums)
}
func initNums(count int) {
rand.Seed(time.Now().UnixNano())
nums = make([]int, count)
for i := 0; i < count; i++ {
nums[i] = rand.Intn(count)
}
}
func BenchmarkSoftNums(b *testing.B) {
initNums(10000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
softNums()
}
} go test -bench="BenchmarkSoftNums" -count=10 | tee quicksoft.txt
go test -bench="BenchmarkSoftNums" -count=10 | tee bubblesoft.txt
benchstat bubblesoft.txt quicksoft.txt
goos: darwin
goarch: arm64
pkg: blog-example/go/benchmark
│ bubblesoft.txt │ quicksoft.txt │
│ sec/op │ sec/op vs base │
SoftNums-10 31942.4µ ± 1% 775.8µ ± 2% -97.57% (p=0.000 n=10)The clear performance difference can be included in reports or GitHub issues.
Some third‑party tools
bench
benchis a Go benchmarking tool that provides integrated performance measurement, automatic performance locking, statistical analysis, and colored output.
funcbench
funcbenchis a Prometheus project tool for automated Go benchmark testing and performance comparison. It supports comparing local branches with GitHub branches, performance locking, and other features useful for large projects.
Reference links
[1] bench: https://github.com/golang-design/bench
[2] funcbench: https://github.com/prometheus/test-infra/tree/master/funcbench
[3] https://dave.cheney.net/high-performance-go-workshop/gophercon-2019.html#welcome
[4] https://golang.design/under-the-hood/zh-cn/part3tools/ch09analysis/perf/
More reading
Go高性能编程 EP1 : empty struct – https://mp.weixin.qq.com/s?__biz=MzU2NjU1MTk1MQ==∣=2247483984&idx=1&sn=13bbe4cdfd841fb0749d71d83f961ec3&scene=21#wechat_redirect
Go高性能编程 EP2: 通过upx 缩小可执行二进制文件的体积 – https://mp.weixin.qq.com/s?__biz=MzU2NjU1MTk1MQ==∣=2247483984&idx=2&sn=54062d19a6705b8f026ecedcdeea836e&scene=21#wechat_redirect
Go高性能编程 EP3: 内存对齐 – https://mp.weixin.qq.com/s?__biz=MzU2NjU1MTk1MQ==∣=2247483984&idx=3&sn=80a6bb13ed828d8924c5f9eadf6f1bd4&scene=21#wechat_redirect
Go高性能编程 EP4: 反射 – https://mp.weixin.qq.com/s?__biz=MzU2NjU1MTk1MQ==∣=2247483984&idx=4&sn=31faf42e171366d7ad748ab225ab27c6&scene=21#wechat_redirect
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
