Go Performance Tuning with pprof: CPU, Memory, GC
Summary: Practical workflow that combines pprof, runtime metrics, and controlled experiments to expose CPU hotspots, excessive allocations, and GC pressure in Go services.
Meta: A production-ready Go tuning checklist: collect pprof profiles, analyze CPU/heap/allocations, tune GC and scheduler knobs, and verify bottlenecks with load tests.
Baseline instrumentation
Start by building the binary with -gcflags=all="-N -l" disabled so pprof symbols are populated. Expose two endpoints:
/debug/pprof/heapand/debug/pprof/profile(vianet/http/pprof).- A simple
/healththat returns summary stats fromexpvarorruntime.ReadMemStats()so the baseline load test can check for stability.
Capture go test -run TestMain style load scenarios if the service is too expensive to run in prod, but always mirror the production flags for CPU scaling and GC settings.
Collecting meaningful profiles
For CPU bottlenecks, run go tool pprof -seconds 30 http://localhost:6060/debug/pprof/profile. Use the --svg output or list mode to inspect heavy functions. Look for self vs cum time; the latter reveals call chains and ensures you do not chase a wrapper routine whose own costs are minimal.
Heap profiles (/debug/pprof/heap) highlight large retention roots. After a load spike, grab a heap profile to spot objects that are not being GC’d. Use pprof commands like top and list to identify the biggest allocation sites. Pay attention to:
- Large
[]bytepools or slices that grow without capacity reuse. - Temporary buffers created inside tight loops (
fmt.Sprintf,json.Marshal). - Global maps that accumulate entries per request.
To separate high-frequency short-lived allocations from long-lived ones, compare successive heap profiles and use peek/ view on .


