Reading the Fire
Raw stack trace counts are hard to read. The standard visualization is the Flamegraph, invented by Brendan Gregg (a performance engineering expert at Netflix and later Google). Flamegraphs turn thousands of stack trace samples into a single, scannable image.
The rules for reading a flamegraph:
- X-Axis (Width): Represents resource consumption — CPU time, memory allocated, or whatever metric is being profiled. The wider the bar, the more of that resource the function consumed. This is the only axis you optimize against.
- Y-Axis (Height): Represents call stack depth. The bottom of the graph is the entry point (e.g.,
main). Each level up is a function called by the one below it. Height tells you about code structure, not performance. - Color: Typically random or used to distinguish packages/modules. Color alone carries no performance meaning unless the tool explicitly documents otherwise.
How to Find the Bottleneck
The debugging workflow is simple:
- Find the widest bar. That function is consuming the most resources.
- Look at its parent (the bar below it). That tells you the call path that led there.
- Decide: is this expected? If
json.Marshalis 40% wide, ask whether you're marshaling more than you should be, or whether you can cache the result.
Common Flamegraph Patterns
| Pattern | What It Looks Like | What It Means |
|---|---|---|
| The Plateau | One very wide, flat bar near the bottom | A single function dominates — clear optimization target |
| The Tower | A tall, narrow spike | Deep call chain but fast execution — usually fine |
| The Forest | Many medium-width bars spread across the bottom | Work is distributed — harder to optimize, may need algorithmic changes |
| The Cliff | A wide bar that suddenly drops off | A function that was slow has been fixed — visible in before/after comparisons |
Interviewers often ask: "How do you use a flamegraph?" A strong answer is: "I look for the widest bars, not the tallest ones. Width represents time spent; height represents call depth. A tall narrow tower is a deep call chain that executes quickly. A wide flat bar is where the CPU is actually spending its time — that's where I start optimizing."