Go pprof Profiling

Go pprof commands and practices for analyzing CPU, memory, goroutine, and block profiles.


Enable Profiling

HTTP Server

 1package main
 2
 3import (
 4    "log"
 5    "net/http"
 6    _ "net/http/pprof"  // Import for side effects
 7)
 8
 9func main() {
10    // Your application code here
11    
12    // Start pprof server
13    go func() {
14        log.Println("pprof server starting on :6060")
15        log.Println(http.ListenAndServe("localhost:6060", nil))
16    }()
17    
18    // Your main application logic
19    select {}
20}

Programmatic Profiling

 1package main
 2
 3import (
 4    "os"
 5    "runtime"
 6    "runtime/pprof"
 7)
 8
 9func main() {
10    // CPU profiling
11    f, _ := os.Create("cpu.prof")
12    defer f.Close()
13    pprof.StartCPUProfile(f)
14    defer pprof.StopCPUProfile()
15    
16    // Your code here
17    doWork()
18    
19    // Memory profiling
20    mf, _ := os.Create("mem.prof")
21    defer mf.Close()
22    runtime.GC() // Get up-to-date statistics
23    pprof.WriteHeapProfile(mf)
24}

CPU Profiling

Capture CPU Profile

1# Via HTTP endpoint (30 seconds)
2curl http://localhost:6060/debug/pprof/profile?seconds=30 > cpu.prof
3
4# Via test
5go test -cpuprofile=cpu.prof -bench=.
6
7# Via runtime/pprof (programmatic)
8# See code example above

Analyze CPU Profile

 1# Interactive mode
 2go tool pprof cpu.prof
 3
 4# Commands in interactive mode:
 5# top       - Show top functions by CPU time
 6# top10     - Show top 10 functions
 7# list main - Show source code for main package
 8# web       - Open graphviz visualization (requires graphviz)
 9# pdf       - Generate PDF report
10# svg       - Generate SVG visualization
11# exit      - Exit
12
13# Direct commands
14go tool pprof -top cpu.prof
15go tool pprof -list=main cpu.prof
16go tool pprof -web cpu.prof
17
18# Compare two profiles
19go tool pprof -base=old.prof new.prof
20
21# Generate flame graph
22go tool pprof -http=:8080 cpu.prof

Memory Profiling

Capture Memory Profile

 1# Heap profile via HTTP
 2curl http://localhost:6060/debug/pprof/heap > heap.prof
 3
 4# Allocs profile (all allocations, not just in-use)
 5curl http://localhost:6060/debug/pprof/allocs > allocs.prof
 6
 7# Via test
 8go test -memprofile=mem.prof -bench=.
 9
10# Via benchmark with allocation stats
11go test -benchmem -bench=.

Analyze Memory Profile

 1# Interactive mode
 2go tool pprof heap.prof
 3
 4# Show allocations
 5go tool pprof -alloc_space heap.prof
 6
 7# Show in-use memory
 8go tool pprof -inuse_space heap.prof
 9
10# Top allocators
11go tool pprof -top heap.prof
12
13# List specific function
14go tool pprof -list=functionName heap.prof
15
16# Web visualization
17go tool pprof -http=:8080 heap.prof
18
19# Compare profiles
20go tool pprof -base=old_heap.prof new_heap.prof

Goroutine Profiling

Capture Goroutine Profile

1# Via HTTP
2curl http://localhost:6060/debug/pprof/goroutine > goroutine.prof
3
4# Full goroutine stack dump
5curl http://localhost:6060/debug/pprof/goroutine?debug=2 > goroutine.txt

Analyze Goroutines

 1# Interactive
 2go tool pprof goroutine.prof
 3
 4# Direct view
 5go tool pprof -top goroutine.prof
 6
 7# Web view
 8go tool pprof -http=:8080 goroutine.prof
 9
10# Text dump (human-readable)
11cat goroutine.txt

Block Profiling

Enable Block Profiling

 1package main
 2
 3import (
 4    "runtime"
 5)
 6
 7func main() {
 8    // Enable block profiling
 9    runtime.SetBlockProfileRate(1)  // 1 = record every blocking event
10    
11    // Your code
12}

Capture and Analyze

1# Via HTTP
2curl http://localhost:6060/debug/pprof/block > block.prof
3
4# Analyze
5go tool pprof block.prof
6go tool pprof -top block.prof
7go tool pprof -http=:8080 block.prof

Mutex Profiling

Enable Mutex Profiling

 1package main
 2
 3import (
 4    "runtime"
 5)
 6
 7func main() {
 8    // Enable mutex profiling
 9    runtime.SetMutexProfileFraction(1)  // Sample 1 in N mutex events
10    
11    // Your code
12}

Capture and Analyze

1# Via HTTP
2curl http://localhost:6060/debug/pprof/mutex > mutex.prof
3
4# Analyze
5go tool pprof mutex.prof
6go tool pprof -http=:8080 mutex.prof

Trace Profiling

Capture Trace

 1package main
 2
 3import (
 4    "os"
 5    "runtime/trace"
 6)
 7
 8func main() {
 9    f, _ := os.Create("trace.out")
10    defer f.Close()
11    
12    trace.Start(f)
13    defer trace.Stop()
14    
15    // Your code
16    doWork()
17}
1# Via HTTP (5 seconds)
2curl http://localhost:6060/debug/pprof/trace?seconds=5 > trace.out
3
4# Via test
5go test -trace=trace.out

Analyze Trace

 1# Open trace viewer
 2go tool trace trace.out
 3
 4# This opens a web browser with:
 5# - View trace: Timeline of goroutines
 6# - Goroutine analysis: Goroutine execution stats
 7# - Network blocking profile
 8# - Synchronization blocking profile
 9# - Syscall blocking profile
10# - Scheduler latency profile

Benchmarking with Profiling

 1# CPU profile
 2go test -bench=. -cpuprofile=cpu.prof
 3
 4# Memory profile
 5go test -bench=. -memprofile=mem.prof
 6
 7# Both
 8go test -bench=. -cpuprofile=cpu.prof -memprofile=mem.prof
 9
10# With allocation stats
11go test -bench=. -benchmem
12
13# Specific benchmark
14go test -bench=BenchmarkMyFunc -cpuprofile=cpu.prof
15
16# Run longer for more accurate results
17go test -bench=. -benchtime=10s -cpuprofile=cpu.prof

pprof Commands Reference

Top-level Commands

 1# top [N]         - Show top N entries (default 10)
 2# list <regex>    - Show source code for functions matching regex
 3# web             - Open graphviz visualization
 4# weblist <regex> - Show annotated source in browser
 5# pdf             - Generate PDF report
 6# svg             - Generate SVG
 7# png             - Generate PNG
 8# gif             - Generate GIF
 9# dot             - Generate DOT file
10# tree            - Show call tree
11# peek <regex>    - Show callers and callees
12# disasm <regex>  - Show disassembly
13# exit/quit       - Exit pprof

Options

1# -flat           - Sort by flat (self) time
2# -cum            - Sort by cumulative time
3# -alloc_space    - Show allocation space
4# -alloc_objects  - Show allocation count
5# -inuse_space    - Show in-use space
6# -inuse_objects  - Show in-use object count
7# -base <file>    - Compare against base profile
8# -http=:8080     - Start web interface

Continuous Profiling

Automated Collection

 1package main
 2
 3import (
 4    "fmt"
 5    "os"
 6    "runtime/pprof"
 7    "time"
 8)
 9
10func collectProfiles() {
11    ticker := time.NewTicker(5 * time.Minute)
12    defer ticker.Stop()
13    
14    for range ticker.C {
15        timestamp := time.Now().Format("20060102-150405")
16        
17        // CPU profile
18        cpuFile, _ := os.Create(fmt.Sprintf("cpu-%s.prof", timestamp))
19        pprof.StartCPUProfile(cpuFile)
20        time.Sleep(30 * time.Second)
21        pprof.StopCPUProfile()
22        cpuFile.Close()
23        
24        // Heap profile
25        heapFile, _ := os.Create(fmt.Sprintf("heap-%s.prof", timestamp))
26        pprof.WriteHeapProfile(heapFile)
27        heapFile.Close()
28    }
29}
30
31func main() {
32    go collectProfiles()
33    
34    // Your application
35}

Best Practices

  1. Profile in production-like environment - Dev machines may not reflect production
  2. Run long enough - At least 30 seconds for CPU profiling
  3. Use benchmarks - For repeatable profiling
  4. Compare profiles - Use -base to see improvements
  5. Focus on hot paths - Optimize top functions first
  6. Profile before optimizing - Don't guess, measure
  7. Check allocations - Use -benchmem to see allocation impact
  8. Use trace for concurrency - Better than pprof for goroutine issues

Example Workflow

 1# 1. Write benchmark
 2cat > main_test.go <<EOF
 3package main
 4
 5import "testing"
 6
 7func BenchmarkMyFunc(b *testing.B) {
 8    for i := 0; i < b.N; i++ {
 9        MyFunc()
10    }
11}
12EOF
13
14# 2. Run benchmark with profiling
15go test -bench=. -cpuprofile=cpu.prof -memprofile=mem.prof -benchmem
16
17# 3. Analyze CPU profile
18go tool pprof -http=:8080 cpu.prof
19
20# 4. Analyze memory profile
21go tool pprof -http=:8081 mem.prof
22
23# 5. Make optimizations
24
25# 6. Run again and compare
26go test -bench=. -cpuprofile=cpu_new.prof
27go tool pprof -base=cpu.prof cpu_new.prof

Related Snippets