Debugging & Profiling¶
Tools and techniques for debugging and profiling Go applications.
Debugging¶
Delve Debugger¶
Install Delve:
Start debugging:
# Debug the entire package
dlv debug ./...
# Debug a specific file
dlv debug ./cmd/server.go
# Attach to running process
dlv attach <pid>
Common Delve Commands¶
| Command | Shortcut | Description |
|---|---|---|
break main.go:10 |
b |
Set breakpoint |
break foo.go:15 |
Set breakpoint at line | |
continue |
c |
Run until breakpoint |
next |
n |
Step over line |
step |
s |
Step into function |
out |
o |
Step out of function |
print variable |
p |
Print variable value |
locals |
Print local variables | |
stack |
bt |
Print stack trace |
exit |
q |
Quit debugger |
Example Debug Session¶
(dlv) break internal/core/services/user.go:25
(dlv) continue
> internal/core/services/user.go:25
user.go:25 return s.store.GetUser(ctx, id)
(dlv) print id
"123"
(dlv) locals
ctx = context.Background
id = "123"
(dlv) continue
Profiling¶
CPU Profiling¶
# Run with CPU profiling enabled
go test -cpuprofile=cpu.prof -bench=.
# Or for the application
go run -cpuprofile=cpu.prof main.go run
Analyze the profile:
go tool pprof cpu.prof
# Interactive commands:
(pprof) top
(pprof) top25
(pprof) list FunctionName
(pprof) web
Memory Profiling¶
# Run with memory profiling
go test -memprofile=mem.prof -bench=.
# Analyze
go tool pprof mem.prof
(pprof) top
(pprof) top -cum
(pprof) list FunctionName
Block Profiling¶
Identifies synchronization bottlenecks:
Mutex Profiling¶
Find lock contention:
Benchmarks¶
Running Benchmarks¶
# Run all benchmarks
go test -bench=. -benchmem ./...
# Run specific benchmark
go test -bench=^BenchmarkUserCreate$ -benchmem ./...
# Run with CPU profiling
go test -bench=. -benchmem -cpuprofile=cpu.out ./...
Benchmark Example¶
func BenchmarkUserService_Create(b *testing.B) {
store := NewMockStore()
service := NewUserService(store)
b.ResetTimer()
for i := 0; i < b.N; i++ {
service.Create(context.Background(), &CreateRequest{
Email: "test@example.com",
})
}
}
Interpreting Results¶
BenchmarkUserService_Create-8 1000000 1234 ns/op 256 B/op 3 allocs/op
↑ ↑ ↑ ↑ ↑
Name Iterations Time/op Memory Allocations
Comparing Benchmarks¶
# Save baseline
go test -bench=. -count=5 > baseline.txt
# After changes
go test -bench=. -count=5 > new.txt
# Compare with benchstat
go install golang.org/x/tools/cmd/benchstat@latest
benchstat baseline.txt new.txt
Tracing¶
Generate Trace¶
View Trace¶
Trace shows:
- Goroutine scheduling
- Syscall blocking
- GC events
- User-defined tasks
pprof Web Interface¶
Generate a profile and view in browser:
This opens a browser with:
- Graph visualization
- Source code view
- Flame graph
- Call tree
Common Performance Issues¶
| Issue | Profiling Type | Solution |
|---|---|---|
| High CPU | CPU profile | Optimize hot functions |
| Memory leaks | Memory profile | Check retained objects |
| Slow requests | CPU + trace | Find blocking operations |
| Lock contention | Mutex profile | Reduce critical sections |
| Excessive allocs | Mem profile | Reduce allocations |
Runtime Metrics¶
GODEBUG Settings¶
# Show GC trace
GODEBUG=gctrace=1 go run main.go
# Show scheduler trace
GODEBUG=schedtrace=1000 go run main.go
Prometheus Metrics¶
If observability is enabled:
# View metrics
curl http://localhost:9090/metrics
# Common metrics:
# - go_goroutines
# - go_memstats_alloc_bytes
# - process_cpu_seconds_total
Integration with IDE¶
VS Code¶
Install Go extension, then:
- Set breakpoints in code
- Press F5 to start debugging
- Use Debug Console to inspect variables
GoLand¶
- Run → Edit Configurations
- Add Go Remote or Go Test configuration
- Set breakpoints and run
Quick Reference¶
| Task | Command |
|---|---|
| Debug a test | dlv test ./... |
| CPU profile | go test -cpuprofile=pprof.out |
| Memory profile | go test -memprofile=pprof.out |
| Benchmarks | go test -bench=. -benchmem |
| View profile | go tool pprof pprof.out |
| Generate trace | go test -trace=trace.out |
| View trace | go tool trace trace.out |