pprof

The visualization and analysis tool for profile.proto performance profiles, with interactive, graph, and web-based views.

Tool
Go
vv0.0.0-20260906184651-6331bc6350fe
9,281stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
73/100Good
Development Activity84
Maintenance36
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture80
Code Quality85
Innovation78
Learning Curve80

pprof is Google’s tool for visualizing and analyzing profiling data in the profile.proto format — the same wire format produced by Go’s runtime/pprof and net/http/pprof, and now used as a common interchange format across the profiling ecosystem. It reads one or more compressed profile files, or fetches a profile live over HTTP from a running process, and turns raw call-stack samples into text reports, Graphviz-rendered call graphs, or a full interactive web UI with flame graphs and source/disassembly annotation.

Because it operates on the wire format rather than a single language’s runtime, pprof can symbolize and diff profiles from any tool that emits profile.proto, using native binutils integration (addr2line, nm) and multi-language symbol demangling (C++, Rust, Swift) to resolve raw addresses back to function names and source lines.

What You Get

  • Three report modes — a -top-style text report, a Graphviz-rendered SVG call graph, and a full -http web UI with flame graphs
  • Native symbolization via addr2line/nm and demangling of C++, Rust, and Swift symbols
  • Support for aggregating and diffing multiple profiles (e.g. before/after comparisons)
  • An importable profile Go package for parsing, encoding, and manipulating profile.proto data programmatically
  • Support for reading perf.data files (via the companion perf_data_converter project) alongside native Go profiles

Common Use Cases

  • Debugging a CPU hotspot - a Go developer profiles a slow service with net/http/pprof, then runs pprof -top against the captured profile to find the hottest call stacks
  • Comparing before/after performance - an engineer profiles the same workload before and after a change and uses pprof’s diff mode to see which functions regressed
  • Visualizing memory allocation - a team investigating a memory leak generates an -http flame graph from a heap profile to see which allocation paths dominate
  • Building custom profiling tooling - a platform team imports the profile package directly to parse, filter, and re-encode profile.proto data as part of an internal continuous-profiling pipeline

Under The Hood

Architecture The main package (pprof.go) wires a readline-backed terminal UI into driver.PProf (driver/driver.go), a thin public wrapper around the real engine in internal/driver. That internal package dispatches to an interactive shell, a static report renderer, or the embedded web UI (internal/driver/webui.go plus the html/ templates and third_party/svgpan) depending on the flags passed. Supporting internal packages handle native symbolization (internal/binutils, internal/elfexec, internal/symbolizer, internal/symbolz), graph construction and rendering (internal/graph, internal/report), and unit handling (internal/measurement) — kept unexported so the engine can evolve freely behind the two stable public entry points, profile and driver. The profile.Profile struct is the central in-memory model threaded through every stage of the pipeline, so a change to its shape would ripple through symbolization, filtering, and every report-rendering path.

Tech Stack A Go module (go 1.25) with a deliberately small dependency surface: github.com/chzyer/readline for the interactive shell, github.com/ianlancetaylor/demangle for C++/Rust/Swift symbol demangling, and golang.org/x/sys as an indirect dependency. The -http mode is a plain net/http server serving embedded HTML/JS/CSS assets rather than a web framework, and it shells out to Graphviz’s dot plus binutils’ addr2line/nm for graph rendering and address symbolization. Profile data itself is protocol-buffer-encoded per proto/profile.proto, decoded through the profile package’s own hand-written encode/decode rather than the standard protobuf runtime. It ships as a single static binary via go install, with a GitHub Actions CI matrix (ci.yaml) exercising multiple Go versions across macOS, Linux, and Windows.

Code Quality An extensive test suite — over thirty _test.go files — covers the profile package (encoding round-trips, merging, filtering, pruning, legacy-format decoding) and internal/driver (command dispatch, interactive mode, the web UI, HTTP fetching), plus a dedicated fuzz corpus for profile decoding. Errors are returned explicitly as Go error values throughout rather than panicking, and naming follows standard Go conventions. There’s no dedicated linter config checked in, but the CI matrix runs the full test suite across multiple Go versions and operating systems on every push and nightly.

What Makes It Unique pprof’s distinguishing choice is being both the reference implementation of the profile.proto wire format — adopted well beyond Go as a de facto interchange format for continuous-profiling systems — and a fully interactive analysis tool with three complementary UI modes built around one shared in-memory model: a readline shell, static Graphviz-rendered graphs, and a built-in web UI with flame graphs, source annotation, and diff-between-profiles views. Its native symbolization support, including addr2line/nm integration and multi-language demangling, sets it apart from profilers that only resolve symbols within their own language runtime.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search