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=.
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
-benchmem
flag to report memory allocations when running benchmarks. - Profile your code with
pprof
to 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.