Flame graph

A flame graph visualises aggregated stack traces from a sampling profiler: each box is a stack frame, its width is the proportion of samples in which that frame was on the stack, and boxes stack upward from caller to callee. Brendan Gregg introduced the form in 2011; it is now the default output of nearly every profiler.

Reading one

  • Width = total time. The share of samples where the frame was present, whether running or waiting on something it called.
  • Height = stack depth. Each row is one frame deeper.
  • The top edge is where the CPU actually was. A frame's own "self time" is the part of its width not covered by children.
  • The x-axis is alphabetical. Not chronological.

That last point is the standard misreading. Stacks are sorted by name so identical ones merge into a single wide box — which is the entire trick that makes a million samples legible. A wide box means a lot of total time, not a long contiguous stretch.

Look for plateaus: a wide, flat top edge is code executing directly, and is where optimisation pays. A tall, narrow tower is deep call structure that is rarely on CPU — interesting, but not the bottleneck.

Variants

Variant Difference
Icicle Grows downward. Chrome DevTools' default
Differential Coloured by delta between two profiles
Off-CPU Samples blocked time instead of running time
Memory / alloc Width is bytes allocated, not samples

The default colour palette carries no meaning — it is warm hues chosen to look like flame. Only differential graphs encode information in colour.

Where they come from

perf plus Gregg's flamegraph.pl, async-profiler on the JVM, py-spy and Scalene in Python, pprof in Go, speedscope as a cross-format viewer, Clinic.js in Node, Memray for Python allocations. Most emit a self-contained interactive HTML page (share a flame graph).

Why the interactive version is the only useful one

A flame graph screenshot is nearly worthless. What makes it a tool is:

  • Click to zoom into a subtree and re-normalise the widths.
  • Search, which highlights every matching frame and reports the cumulative percentage across the graph.
  • Hover for exact sample counts and percentages.
  • Legible frame labels, which only appear once zoomed.

Flattening it into an image for a chat message destroys all four, and leaves the reader arguing about a picture. Publishing the HTML keeps the zoom and search working, and lets a reviewer select the plateau they are asking about and comment on it (comment on HTML).

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish a profile →

Related