pprof Profiling
Node.js profiling vs Go pprof
Section titled “Node.js profiling vs Go pprof”In Node.js you have node --prof (V8 CPU profiler), node --inspect (Chrome DevTools), and tools like clinic.js (clinic doctor, clinic flame) for heap and event-loop analysis. All are out-of-process or require wrapping your start command.
Go ships with runtime/pprof in the standard library and net/http/pprof for live HTTP-based profiling — no external tools needed for collection, and the go tool pprof command handles analysis.
Playground note: pprof requires writing profile files to disk and running
go tool pprof. The code blocks below are real files — run them locally.
Two ways to collect profiles
Section titled “Two ways to collect profiles”1. File-based (for scripts or benchmarks)
Section titled “1. File-based (for scripts or benchmarks)”package main
import ( "os" "runtime/pprof" "log")
func main() { // --- CPU profile --- cpuFile, err := os.Create("cpu.out") if err != nil { log.Fatal(err) } defer cpuFile.Close()
if err := pprof.StartCPUProfile(cpuFile); err != nil { log.Fatal(err) } defer pprof.StopCPUProfile()
// ... your code under test ... doWork()
// --- Heap profile (write at the end) --- heapFile, err := os.Create("mem.out") if err != nil { log.Fatal(err) } defer heapFile.Close()
pprof.WriteHeapProfile(heapFile)}2. HTTP endpoint (for long-running servers)
Section titled “2. HTTP endpoint (for long-running servers)”package main
import ( "net/http" _ "net/http/pprof" // blank import registers /debug/pprof/ routes "log")
func main() { // Your application server go func() { log.Println(http.ListenAndServe(":6060", nil)) }()
// ... rest of app ...}Available endpoints:
http://localhost:6060/debug/pprof/— indexhttp://localhost:6060/debug/pprof/profile?seconds=30— 30-second CPU profilehttp://localhost:6060/debug/pprof/heap— heap snapshothttp://localhost:6060/debug/pprof/goroutine— all goroutine stackshttp://localhost:6060/debug/pprof/trace?seconds=5— execution trace
// Node.js — several tools, all external// Option 1: built-in V8 profilernode --prof server.jsnode --prof-process isolate-*.log > report.txt
// Option 2: clinic.js (npm install -g clinic)clinic doctor -- node server.jsclinic flame -- node server.js
// Option 3: Chrome DevToolsnode --inspect server.js // open chrome://inspect// Go — single tool, ships with the toolchain// Collect a 30-second CPU profile from a live server:go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
// Collect from a file written by runtime/pprof:go tool pprof cpu.out
// Open an interactive web UI (needs Graphviz):go tool pprof -http=:8080 cpu.outReading a CPU profile
Section titled “Reading a CPU profile”# Start interactive pprof shellgo tool pprof cpu.out
# Inside the shell:(pprof) top10 # top 10 functions by CPU time(pprof) list myFunc # annotated source for myFunc(pprof) web # open SVG flame graph in browser(pprof) pdf # save as PDF
# Or open the web UI directly (nicer flame graphs)go tool pprof -http=:8080 cpu.outExample top10 output:
Showing nodes accounting for 2.40s, 96.77% of 2.48s total flat flat% sum% cum cum% 1.20s 48.39% 48.39% 1.20s 48.39% runtime.mallocgc 0.60s 24.19% 72.58% 0.60s 24.19% strings.(*Builder).WriteString 0.30s 12.10% 84.68% 0.30s 12.10% main.processItem| Column | Meaning |
|---|---|
flat | Time spent in this function (excluding callees) |
flat% | Percentage of total profile time |
cum | Cumulative time (this function + all functions it called) |
cum% | Cumulative percentage |
Heap profile
Section titled “Heap profile”go tool pprof mem.out
(pprof) top10 -cum # top allocators by cumulative bytes(pprof) list myFunc # line-level allocation countsA heap profile shows:
- alloc_objects / alloc_space — total allocations since program start
- inuse_objects / inuse_space — objects/bytes currently in use (after GC)
Benchmarks + pprof together
Section titled “Benchmarks + pprof together”# Write CPU + memory profiles during a benchmark rungo test -bench=BenchmarkFoo -cpuprofile=cpu.out -memprofile=mem.out ./...
# Then analysego tool pprof cpu.outgo tool pprof mem.outGoroutine and trace profiles
Section titled “Goroutine and trace profiles”# Check for goroutine leaks (should stay flat over time)go tool pprof http://localhost:6060/debug/pprof/goroutine
# Execution trace — shows scheduling, GC, goroutine lifecyclecurl -s "http://localhost:6060/debug/pprof/trace?seconds=5" > trace.outgo tool trace trace.outThe execution trace is the most detailed view: it shows every goroutine start/stop, GC pause, network block, and system call — similar to what clinic doctor does for Node’s event loop.