We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Integrating pprof

The first step toward profiling is integrating pprof and exposing its data. The runtime/pprof package gathers performance data from the Go runtime as your code runs, and writes it in a format we can use.

The package exposes a number of functions for profiling, but the good news is that you can ignore most of them.

While we rely on the package to do the nitty-gritty of runtime profiling, we rarely need to interact directly with it – it's mostly automatic!

Exposing pprof Data

There are a few different ways to expose pprof's data, but for a web app, we'll use the net/http/pprof package. This package does two things for us:

  1. It activates pprof profiling so we don't need to interact directly with runtime/pprof.
  2. It gives us some ready-made HTTP handlers that we can mount using our existing ServeMux.

As a bonus, this package automatically registers its default handlers with the default ServeMux simply by importing it.

package main

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

func main() {
	log.Println(http.ListenAndServe("localhost:6060", nil))
}

This program starts an HTTP server on port 6060, using the default ServeMux, which exposes the default pprof endpoints:

Using the default ServeMux isn't ideal in a real application, so we should explicitly register the handlers we know we want, where we want them. This is also easily accomplished:

import "net/http/pprof"

mux := http.NewServeMux()

/* register all your normal handlers */

mux.HandleFunc("GET /debug/pprof/", pprof.Index)
mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)

pprof.Index handles most endpoints (heap, goroutine, allocs, etc.), but a few – like pprof.Profile for CPU profiling – need their own handler registration.

By mounting the pprof handlers explicitly we have full control, for example, we might want them behind authentication middleware so that only admins can access them:

mux.Handle("GET /debug/pprof/", s.authMiddleware(http.HandlerFunc(pprof.Index)))
mux.Handle("GET /debug/pprof/profile", s.authMiddleware(http.HandlerFunc(pprof.Profile)))

Many teams only mount these handlers in development (or behind strict auth in production), since profiling endpoints can expose sensitive internal details:

if os.Getenv("ENVIRONMENT") == "development" {
	mux.Handle("GET /debug/pprof/", s.authMiddleware(http.HandlerFunc(pprof.Index)))
	mux.Handle("GET /debug/pprof/profile", s.authMiddleware(http.HandlerFunc(pprof.Profile)))
}

Assignment

go run .

Run and submit the CLI tests from the root of the Linko repo.