NOTE
4.2 pprof
Profiling Go programs with CPU, heap, allocation, goroutine, mutex, and block profiles, plus a measurement-first workflow for finding performance bottlenecks.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What Is pprof?
pprof is Go’s profiling ecosystem for collecting sampled runtime data and analyzing where a program spends CPU time or retains/allocates memory.
Two common entry points are:
runtime/pproffor programmatic profile collection;net/http/pproffor exposing profiling endpoints in a running server.
2. CPU Profiling
A CPU profile samples executing stacks over a time window.
f, _ := os.Create("cpu.pprof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
Analyze it with:
go tool pprof cpu.pprof
go tool pprof -http=:9090 cpu.pprof
Useful views include:
top— highest flat/cumulative CPU consumers;top -cum— rank by cumulative cost;list <func>— map cost back to source lines;- graph / flame-graph-style views for call paths.
Flat cost belongs directly to a function’s sampled execution; cumulative cost includes descendants in its call tree.
3. Heap and Allocation Profiles
Heap profiles help answer two different questions:
- what memory is currently live (
inuse_*); - where allocations have accumulated over time (
alloc_*).
A large allocation source is not automatically a leak. A leak is about retention or unbounded lifetime, so compare profiles over time and inspect what remains reachable.
See Go Memory Leaks.
4. HTTP Profiling
Import the handler package and expose it only on an appropriately protected diagnostic endpoint:
import _ "net/http/pprof"
Profiles commonly include:
profile— CPU;heap/allocs— memory;goroutine— goroutine stacks;mutex— mutex contention;block— blocking events;threadcreate— OS thread creation.
Do not expose pprof endpoints publicly without access control: profiles and stack traces can reveal sensitive implementation details.
5. A Practical Workflow
- reproduce the problem with a representative workload;
- capture the profile that matches the symptom;
- identify the dominant stack/function;
- inspect source and call paths;
- change one bottleneck;
- profile again and compare.
Benchmarking tells you how much performance changed; profiling helps explain where the time or memory went.