Performance Basics
9 examples to get you started with Performance - 7 basic and 2 intermediate.
Search across all documentation pages
9 examples to get you started with Performance - 7 basic and 2 intermediate.
mkdir perflab && cd perflab && go mod init example.com/perflab.perflab_test.go package.go install golang.org/x/perf/cmd/benchstat@latest for comparing benchmark runs.Measure how long a function takes per iteration with testing.B.
package perflab
import "testing"
func Sum(n int) int {
s := 0
for i := 0; i < n; i++ {
s += i
}
return s
}
func BenchmarkSum(b *testing.B) {
for b.Loop() {
Sum(1000)
}
}go test -bench=BenchmarkSum ./...BenchmarkXxx functions live in *_test.go files.b.Loop() (Go 1.24+) replaces manual b.N loops and resets timers correctly.ns/op - nanoseconds per loop iteration.Related: Benchmarks with testing.B & B.Loop - benchmark depth
Report bytes and allocations per operation alongside timing.
import "strings"
func BenchmarkJoin(b *testing.B) {
parts := []string{"a", "b", "c", "d"}
b.ReportAllocs()
for b.Loop() {
_ = strings.Join(parts, ",")
}
}go test -bench=BenchmarkJoin -benchmem ./...-benchmem adds B/op (bytes per op) and allocs/op columns.b.ReportAllocs() ensures alloc counts appear even without -benchmem.allocs/op in hot paths often matters more than a few nanoseconds.Related: Slice Preallocation, strings.Builder & map Pre-sizing - reducing allocs
Write a CPU profile file while benchmarks run.
go test -cpuprofile=cpu.prof -bench=BenchmarkJoin ./...
go tool pprof -top cpu.prof-cpuprofile samples the process during the benchmark only.go tool pprof -top prints the hottest functions by flat CPU time.Related: CPU & Heap Profiling with pprof - full pprof workflow
Capture heap allocation sites during a test or benchmark.
go test -memprofile=heap.prof -bench=BenchmarkJoin ./...
go tool pprof -top -alloc_space heap.prof-memprofile records allocation samples.-alloc_space sorts by total bytes allocated; -inuse_space shows live heap.-benchmem to connect micro numbers to call sites.Related: CPU & Heap Profiling with pprof - reading heap graphs
Expose profiles on a running HTTP server for load-test collection.
package main
import (
_ "net/http/pprof"
"net/http"
)
func main() {
go func() {
http.ListenAndServe("localhost:6060", nil)
}()
// ... your service on another port
}go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30_ "net/http/pprof" registers /debug/pprof/* on DefaultServeMux.6060 on localhost or protect with auth in production.Related: Performance in Go: Measure, Profile, Then Optimize - measurement culture
Explore flame graphs in the browser.
go tool pprof -http=:8081 cpu.profFocus and Ignore to narrow noisy stdlib frames.Related: CPU & Heap Profiling with pprof - flame graph reading
Print garbage collector timing and heap size to stderr.
GODEBUG=gctrace=1 go run .GOGC or GOMEMLIMIT.Related: GC Tuning for Latency-Sensitive Services - GC experiments
Record baseline and candidate benchmark output, then compare statistically.
go test -bench=BenchmarkJoin -count=10 ./... > old.txt
# change code
go test -bench=BenchmarkJoin -count=10 ./... > new.txt
benchstat old.txt new.txt-count=10 reduces noise from CPU frequency scaling and cache state.benchstat reports whether deltas are significant, not just faster on one run.GOMAXPROCS) when publishing numbers.Related: Benchmarks with testing.B & B.Loop - bench hygiene
Mount pprof on a custom mux with timeouts and localhost binding.
package main
import (
"net/http"
_ "net/http/pprof"
"time"
)
func main() {
admin := http.NewServeMux()
admin.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
// pprof routes registered on DefaultServeMux; mount them:
admin.Handle("/debug/", http.DefaultServeMux)
srv := &http.Server{
Addr: "127.0.0.1:6060",
Handler: admin,
ReadHeaderTimeout: 5 * time.Second,
}
_ = srv.ListenAndServe()
}ReadHeaderTimeout blocks slowloris on the admin port too.6060 during incidents instead of exposing it publicly.Related: net/http Basics - server patterns
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026