Benchmarking Go Code
Learn how to benchmark your Go code using the testing package to measure performance and optimize accordingly
Benchmarking is a crucial practice to measure the performance of your Go code and identify bottlenecks. The Go standard library provides a testing package which is well-suited for benchmarking.
Basic Benchmark Function
Here's a simple example of a benchmark function to measure the performance of a function:
package main
import (
"testing"
)
// Function to benchmark.
func Sum(x, y int) int {
return x + y
}
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Sum(1, 2)
}
}
To run the benchmark, use the command: go test -bench=.
Go 1.24+ Benchmark with b.Loop Function
You can achieve the same functionality with the b.Loop method:
package main
import (
"testing"
)
// Function to benchmark.
func Sum(x, y int) int {
return x + y
}
func BenchmarkSum(b *testing.B) {
for b.Loop() {
_ = Sum(1, 2)
}
}
This method prevents unwanted compiler optimizations and automatically handles setup and cleanup for you.
Benchmarking with Setup and Teardown
Often you'll want to include setup or teardown logic with your benchmarks:
package main
import (
"testing"
)
func ExpensiveSetup() int {
// Simulate an expensive operation.
return 42
}
func BenchmarkWithSetupTeardown(b *testing.B) {
data := ExpensiveSetup()
b.ResetTimer() // Reset timer after setup
for i := 0; i < b.N; i++ {
_ = data + i
}
b.StopTimer() // Stop timer before teardown
}
Benchmarking with Parallelism
You can test how well your code performs using parallel execution:
package main
import (
"testing"
)
func ParallelTask() {
// Simulate some work.
}
func BenchmarkParallelTask(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ParallelTask()
}
})
}
Best Practices
- Use
b.ResetTimer()after any setup to ensure only the execution time of the code you're benchmarking is measured. - Use
b.StopTimer()andb.StartTimer()around parts of the benchmark that shouldn't be timed, like setup and teardown. - Be mindful of external system effects — ensure controlled conditions to get consistent results.
- Use benchmarks to explore different variations of your code for optimization opportunities.
Common Pitfalls
- Forgetting to reset the timer (
b.ResetTimer()) after setup. - Running benchmarks on a machine with varying loads can result in inconsistent results.
- Failing to ensure benchmark code does meaningful work; avoid empty loops that the compiler might optimize away.
- Not using parallel benchmarks for functions intended to be used concurrently.
Performance Tips
- Consider using
-benchmemflag to report memory allocations when running benchmarks. - Profile your code with
pprofto find hotspots and memory usage patterns. - Compare benchmarks before and after changes to evaluate their impact on performance.
- Experiment with different sizes or types of input data to see how they affect performance.
- Use the
b.ReportAllocs()method to ensure memory allocations are reported.