Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
The cardinal sin of performance is guessing. Every language has a profiler — pprof in Go, py-spy or cProfile in Python, flamegraph in Rust, --prof or 0x in Node. Before you cache, rewrite, or rearchitect, run a profiler against a realistic load and look at where the time actually goes. The answer is almost never where you expected. Spending 30 minutes profiling saves you days of optimizing the wrong thing.
A load test tells you what your server's throughput ceiling is; a flame graph tells you why. CPU profilers sample the call stack thousands of times per second and aggregate into a chart where width equals total CPU time — wide bars are where time is actually spent. Attaching one to a running server under load often reveals surprising hot spots: JSON serialisation, string allocation, a middleware nobody remembers adding.
-c100 -d30s). Collect a 20-second profile.Use these three in order. Each builds on the one before.
Explain what a flame graph is and how to read one. What do the width, the color, and the stack direction each mean?
Walk me through how a sampling profiler (py-spy, pprof, perf) actually works: at N Hz it interrupts the target process, reads the stack, records it. Why 'sampling' instead of 'tracing every call'? What's lost and gained?
Your flame graph shows that 40% of the time is in a function called `unmarshal_json`. The obvious fix: switch JSON libraries. Before you do — what are the three questions you'd ask to make sure that's the right optimization, and not just the most visible one?
// 1. Import net/http/pprof — one line, exposes profiling endpoints
package main
import (
"net/http"
_ "net/http/pprof"
)
// 2. Your server runs as before; pprof adds /debug/pprof/* automatically.
// 3. While your server is under load (wrk -c100 -d30s), in another terminal:
// go tool pprof http://localhost:8080/debug/pprof/profile?seconds=20
// (pprof) top
// (pprof) list slowFunction
// (pprof) web # opens a browser flame graph
// You'll see the hot path of your handler in 30 seconds.go run main.go