Performance Optimization in Go
Go is designed for performance, but writing fast Go code requires understanding the runtime, memory model, and profiling tools. This chapter covers practical techniques for optimizing Go applications.Profiling with pprof
Go’s built-in profiler helps identify performance bottlenecks.CPU Profiling
Memory Profiling
HTTP pprof Server
http://localhost:6060/debug/pprof/profile- CPU profilehttp://localhost:6060/debug/pprof/heap- Memory profilehttp://localhost:6060/debug/pprof/goroutine- Goroutine stackshttp://localhost:6060/debug/pprof/block- Blocking profilehttp://localhost:6060/debug/pprof/mutex- Mutex contention
Analyzing Profiles
Benchmarking
Writing Benchmarks
Memory Benchmarks
Running Benchmarks
Memory Optimization
Understanding Escape Analysis
Reducing Allocations
String Concatenation
Struct Field Alignment
Concurrency Optimization
Goroutine Pool
Reducing Lock Contention
Atomic Operations
I/O Optimization
Buffered I/O
Connection Pooling
JSON Optimization
Standard Library Tips
Using Faster JSON Libraries
Code Generation
Compiler Optimizations
Inlining
Bounds Check Elimination
Common Anti-Patterns
Defer in Hot Loops
Interface Conversions
Profiling Checklist
- Identify hotspots with CPU profiling
- Check memory allocations with heap profiling
- Find goroutine leaks with goroutine profiling
- Detect lock contention with mutex profiling
- Analyze blocking with block profiling
Interview Questions
How do you identify memory leaks in Go?
How do you identify memory leaks in Go?
- Use
pprofheap profile to see allocations - Check goroutine count over time (
runtime.NumGoroutine()) - Monitor process memory with external tools
- Look for growing maps, slices, or channels
- Check for goroutines blocked forever
What's escape analysis and why does it matter?
What's escape analysis and why does it matter?
Escape analysis determines if a variable can stay on the stack or must escape to the heap. Stack allocation is faster and doesn’t require garbage collection. Use
go build -gcflags="-m" to see escape decisions.How do you reduce GC pressure?
How do you reduce GC pressure?
- Reduce allocations (pre-allocate slices, use sync.Pool)
- Avoid creating many short-lived objects
- Use value types instead of pointers when possible
- Batch operations to amortize allocation cost
- Consider
GOGCtuning for specific workloads
When should you use sync.Pool?
When should you use sync.Pool?
Use sync.Pool for:
- Frequently allocated/deallocated objects
- Objects with predictable lifecycle
- Buffers, temporary structs, connection wrappers
Summary
| Technique | When to Use |
|---|---|
| CPU Profiling | Identify slow functions |
| Memory Profiling | Find allocation hotspots |
| Benchmarking | Measure and compare performance |
| sync.Pool | Reduce GC pressure for temp objects |
| Sharding | Reduce lock contention |
| Buffered I/O | Reduce system calls |
| Pre-allocation | Avoid slice/map growth |
| Atomic Operations | Simple concurrent counters |