Performance matters β especially when dealing with large-scale systems or performance-critical code. Go (Golang) provides first-class support for benchmarking via the testing package. This article walks you through the fundamentals of benchmarking in Go: what it is, why it's important, and how to run benchmarks to compare multiple functions.
π§ What is Benchmarking?
Benchmarking is the process of measuring how efficiently a piece of code executes. In Go, this typically involves determining how long a function takes to run, how many resources it uses, or how well it scales under load.
Benchmarking is different from testing β it doesnβt check if your code is correct but it checks how well it performs.
β Why We Should Do Benchmarking
Benchmarking is useful when you want to:
-
Compare different implementations of the same logic (e.g., using
+vsstrings.Builderfor string concatenation). - Find performance bottlenecks in your application.
- Track regressions over time, especially in performance-sensitive systems.
- Make data-driven decisions when optimizing code.
In short, benchmarking gives you quantitative insights into your codeβs behavior under stress.
π» Example
Letβs take an easy and real world example which we often overlook
package benchmark
import (
"strings"
"testing"
)
func concatWithPlus(a, b string) string {
return a + b
}
func concatWithBuilder(a, b string) string {
var sb strings.Builder
sb.WriteString(a)
sb.WriteString(b)
return sb.String()
}
func BenchmarkConcatWithPlus(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = concatWithPlus("Hello", "World")
}
}
func BenchmarkConcatWithBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = concatWithBuilder("Hello", "World")
}
}
βΆοΈ Running the Benchmark
Save the file as concat_test.go and run:
go test -bench=.
π€ Output
Example output might look like:
goos: linux
goarch: amd64
BenchmarkConcatWithPlus-8 10000000 150 ns/op
BenchmarkConcatWithBuilder-8 20000000 90 ns/op
PASS
ok example.com/benchmark 2.345s
π How to Read the Output
Each line shows:
| Field | Meaning |
|---|---|
BenchmarkConcatWithPlus-8 |
Benchmark function run on 8 logical CPUs |
10000000 |
Number of iterations Go used for benchmarking |
150 ns/op |
Average time taken for one operation (in nanoseconds) |
In this case:
-
concatWithBuilderis faster (90 ns/op) thanconcatWithPlus(150 ns/op). - Therefore,
strings.Builderis a more efficient way to concatenate strings in this context.
Optional Memory Metrics
To view memory allocations and usage:
go test -bench=. -benchmem
Sample output:
BenchmarkConcatWithPlus-8 10000000 150 ns/op 16 B/op 1 allocs/op
BenchmarkConcatWithBuilder-8 20000000 90 ns/op 0 B/op 0 allocs/op
| Field | Meaning |
|---|---|
150 ns/op |
How many bytes of memory were allocated per iteration. |
1 allocs/op |
How many memory allocation events occurred per iteration. |
This shows:
-
concatWithPlusallocates memory (16 bytes per operation). -
concatWithBuilderavoids allocations β a big win for performance.
π Conclusion
Benchmarking in Go is easy to set up and incredibly valuable. It helps you:
- Understand the performance characteristics of your code
- Choose the most efficient implementations
- Catch regressions before they ship to production
By comparing two simple functions, we saw how small differences in implementation can lead to measurable performance improvements.
Top comments (0)