# What Is a Flame Graph? — Reading Profiles, and Why the X-Axis Isn't Time

Canonical: https://commareports.com/glossary/flamegraph
Published: 2026-09-11

> A flame graph visualises aggregated stack samples: width is total time in a function, depth is stack depth, and the x-axis is alphabetical. How to read one, and icicle versus differential.

# 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](/share-flamegraph)).

## 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](/comment-on-html)).

## Try it

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

**[Publish a profile →](https://commareports.com/)**

### Related

- [Share a flame graph](/share-flamegraph) · [py-spy](/share-py-spy-profile) · [speedscope](/share-speedscope-profile) · [async-profiler](/share-async-profiler-report)
- [Profiling reports](/share-profiling-report) · [Benchmark reports](/share-benchmark-report)
- [Stop screenshotting reports](/stop-screenshotting-reports) · [Glossary](/glossary)
