Profiling with pprof
Go has built-in profiling. Import net/http/pprof and access profiles at /debug/pprof/:
import _ "net/http/pprof"
// CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=10
// Memory profile
go tool pprof http://localhost:6060/debug/pprof/heap
// Goroutine profile (find leaks)
go tool pprof http://localhost:6060/debug/pprof/goroutine
Benchmarks
func BenchmarkStringConcat(b *testing.B) {
for i := 0; i < b.N; i++ {
s := ""
for j := 0; j < 100; j++ { s += "x" }
}
}
func BenchmarkStringBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
var sb strings.Builder
for j := 0; j < 100; j++ { sb.WriteString("x") }
_ = sb.String()
}
}
go test -bench=. -benchmem
Output
BenchmarkStringConcat-8 50000 28432 ns/op 11840 B/op 99 allocs/op BenchmarkStringBuilder-8 1000000 1052 ns/op 504 B/op 7 allocs/op
StringBuilder is 27x faster with 14x fewer allocations. Always benchmark before and after optimization.
Key Takeaway: Profile first, optimize second. Use
go test -bench for micro-benchmarks and pprof for production profiling. The biggest wins come from reducing allocations and using appropriate data structures.Practice Exercises
Hard Production Scenario
Design a solution using these concepts for a real-world production system.
Hard Performance Analysis
Benchmark two different approaches and explain which is better and why.