Go Performance Analysis Made Simple

Go Performance Analysis Made Simple

runtime/pprof

Time - CPU Time Analysis

import "github.com/pkg/profile"

func main() {
	defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
	// code you want to analyze
}
time ./program

This generates a cpu.pprof file. Your program runs longer because profiling needs frequent interrupts to record useful information.

go tool pprof
go tool pprof -http=:8080 cpu.pprof

If syscall.syscall takes up large time, you might be using system calls too often directly or indirectly.

Red arrows show bottlenecks in your program. If linear code takes too long, consider using multiple goroutines (fixed-size worker pool) to speed things up. Change single-line processing to scalable parallel processing. Use trace for further optimization later. Follow Amdahl’s Law when optimizing.

If mallocGC takes too much time, you have memory usage problems. You might be allocating memory too often. Use memory allocation analysis methods to dig deeper.

Space - Memory Allocation Analysis

import "github.com/pkg/profile"

func main() {
	defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()
	// code you want to analyze
}

Default sampling rate is 1 sample per 4096 allocations.

Sample every allocation:

import "github.com/pkg/profile"

func main() {
	defer profile.Start(profile.MemProfile, profile.MemProfileRate(1), profile.ProfilePath(".")).Stop()
	// code you want to analyze
}
go tool pprof
go tool pprof -http=:8080 mem.pprof

View Flame Graph

Open http://localhost:8080/ui/flamegraph

net/http/pprof

Trace Tool

Tracks GC and goroutine scheduling and execution.

import "github.com/pkg/profile"

func main() {
	defer profile.Start(profile.TraceProfile, profile.ProfilePath(".")).Stop()
	// code you want to analyze
}
go tool trace trace.out