Is it time to check why your code is so slow? Golang provides powerful built-in profiling tools to help identify performance bottlenecks.

Setting up pprof

To enable profiling, add pprof handlers to your HTTP server by importing:

import _ "net/http/pprof"

If you’re using the standard HTTP server, this will automatically register handlers at /debug/pprof/.

For custom mux routers (like gorilla/mux), you’ll need to register the handlers explicitly:

import (
    "net/http"
    "net/http/pprof"
)

// Register pprof handlers
router.HandleFunc("/debug/pprof/", pprof.Index)
router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
router.HandleFunc("/debug/pprof/profile", pprof.Profile)
router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
router.HandleFunc("/debug/pprof/trace", pprof.Trace)

Make sure your server is listening on a port (6060 is commonly used for profiling):

http.ListenAndServe(":6060", nil)

Collecting CPU profiles

Run your application, then collect a CPU profile with:

❯ go tool pprof 'http://localhost:6060/debug/pprof/profile?seconds=60'
Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60
Saved profile in /Users/bx2/pprof/pprof.main.samples.cpu.001.pb.gz
File: main
Type: cpu
Time: Mar 19, 2024 at 8:14pm (CET)
Duration: 60.08s, Total samples = 3.79s ( 6.31%)
Entering interactive mode (type "help" for commands, "o" for options)

The seconds parameter controls how long the profiling runs. Longer durations provide more accurate results but require your application to be running longer.

Analyzing profiles

Once in the interactive pprof shell, visualize the profile with:

(pprof) web

This opens a browser with a graph visualization showing which functions consume the most CPU time. Functions taking more time appear larger and with darker colors.

Other useful pprof commands include:

(pprof) top        # Shows top functions by CPU usage
(pprof) list func  # Shows source code with line-by-line profiling data
(pprof) png        # Generates a PNG image of the profile

Memory profiling

To inspect memory usage, you can look at heap profiles. Access the memory profile directly in your browser:

http://localhost:6060/debug/pprof/heap?debug=1

Or analyze it with pprof:

go tool pprof http://localhost:6060/debug/pprof/heap

Other profile types

Go’s pprof offers several profile types:

  • /debug/pprof/profile - CPU profile
  • /debug/pprof/heap - Memory allocations
  • /debug/pprof/block - Goroutine blocking
  • /debug/pprof/mutex - Mutex contention
  • /debug/pprof/goroutine - All goroutines
  • /debug/pprof/threadcreate - OS thread creation

Flame graphs

For a more intuitive visualization, try generating flame graphs:

go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile

This starts a local web server where you can switch between different visualization types, including flame graphs.