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.

Radish, Keep Going!
Radish, Keep Going!
Radish, Keep Going!
Master Go Benchmarks: Accurate Performance Testing and Advanced Tools

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

bench

is a Go benchmarking tool that provides integrated performance measurement, automatic performance locking, statistical analysis, and colored output.

funcbench

funcbench

is 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

backendTestingbenchmarkTools
Radish, Keep Going!
Written by

Radish, Keep Going!

Personal sharing

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.