liveBook · Manning

Profiling

As explained in 100 Go Mistakes and How to Avoid Them

Profiling is the measurement of a program's runtime behavior and resource consumption to identify performance characteristics and bottlenecks.

Optimizing by guesswork can miss the actual bottleneck. Profiling measures what a Go application is doing so you can investigate CPU use, memory use, contention, blocked goroutines, or a possible leak before changing code. section 12.8 section 12.8.1

Choose a profile for the question at hand:

  • CPU: Where does the application spend execution time? section 12.8.1
  • Heap: What is allocated, and does current memory usage suggest a leak? section 12.8.1
  • Goroutine: What are ongoing goroutines doing? section 12.8.1
  • Mutex or block: Where is execution delayed by locks or synchronization? section 12.8.1

A common mistake is to treat a CPU profile as a continuous record of every operation. Go’s CPU profiler samples execution: by default, it interrupts the application every 10 ms, collects activity, then lets execution resume. Requesting `/debug/pprof/profile` starts a 30-second CPU profile by default. Profiling that affects performance is activated for a specific period rather than running continuously. section 12.8.1

package main
 
import (
    "fmt"
    "log"
    "net/http"
    _ "net/http/pprof"                                                      #1
)
 
func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {     #2
        fmt.Fprintf(w, "")
    })
    log.Fatal(http.ListenAndServe(":80", nil))
}

This Go server imports `net/http/pprof` for its side effect, exposing profiling data under `/debug/pprof`. section 12.8.1

$ go test -bench=. -cpuprofile profile.out

For a benchmark, this command writes a CPU profile to `profile.out`; it offers another way to collect evidence before optimizing. section 12.8.1

$ go tool pprof -http=:8080 <file>

Open a collected profile with `go tool pprof` to inspect where execution or resource use is concentrated. section 12.8.1

A goroutine that has not made progress

A goroutine profile can expose a stack trace showing a goroutine waiting on a channel receive for 1,420 minutes. That is a concrete place to investigate; the stack trace alone does not establish why it is waiting. section 12.8.1

Use the execution tracer when the question is how goroutines are scheduled rather than which functions dominate a CPU profile. CPU profiling is sampled and per function; traces show per-goroutine execution without the CPU profiler’s sampling-rate limit. User-defined tasks can add finer boundaries to a trace. section 12.8.2

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains profile types, pprof activation, and CPU sampling mechanics; contrasts CPU profiles with execution traces.
Examples
Uses an HTTP pprof endpoint, benchmark CPU-profile command, profile viewer, and long-blocked goroutine stack trace.
What it assumes
Assumes a Go application or benchmark to measure while introducing profile categories and how to activate pprof.
What you can do after
Apply it via pprof to collect a relevant Go profile and identify where to investigate performance or resource use.
How it connects
Connects profiling to heap allocation, goroutines, mutex contention, synchronization, benchmarks, and execution tracing.

Also explained in

Compare how 11 books explain profiling →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.