Lexikon · F

Flame Graph

Visualisierung gesampelter Stacktraces, in der jeder Kasten eine Funktion ist und seine Breite zeigt, wie oft sie in den Samples vorkam.

Von Obseria-RedaktionAktualisiert

Definition

Ein Flame Graph ist eine Visualisierung hierarchischer Profiling-Daten, meist gesampelter Stacktraces. Jeder Kasten steht für eine Funktion im Stack; die y-Achse zeigt die Stacktiefe, die Breite eines Kastens, wie häufig die Funktion in den Samples vorkam. Die x-Achse ist keine Zeitachse: Frames werden alphabetisch sortiert, damit identische Stacks zusammenfallen.

Was ein Flame Graph ist

Ein Flame Graph verdichtet Tausende Stacktraces zu einem Bild, das zeigt, wo ein Programm seine Zeit verbringt. Brendan Gregg entwickelte die Darstellung 2011 bei der Performance-Analyse von MySQL, weil das Lesen der Rohausgabe von Profilern zu lange dauerte. Heute sind Flame Graphs die Standardansicht in CPU-Profilern, Continuous-Profiling-Werkzeugen, Browser-Entwicklertools und Observability-Plattformen.

Grundlage ist meist ein Sampling-Profil. Ein Profiler wie Linux perf, async-profiler für die JVM, pprof für Go oder ein eBPF-basierter Profiler unterbricht das Programm in fester Frequenz, häufig 99- oder 100-mal pro Sekunde, und zeichnet den aktuellen Call Stack auf. Identische Stacks werden gezählt; der Flame Graph zeichnet jeden eindeutigen Stack als Säule aus Kästen, deren Breite proportional zur Anzahl ist.

So lesen Sie einen Flame Graph

  • Jeder Kasten ist ein Stack Frame, meist eine Funktion. Der Kasten direkt darüber ist eine Funktion, die sie aufgerufen hat.
  • Die y-Achse ist die Stacktiefe. Im klassischen Layout liegt die Wurzel (etwa der Einstiegspunkt des Threads) unten, die Blattfunktionen oben. Die Oberkante zeigt also, was beim Sampling tatsächlich auf der CPU lief.
  • Die x-Achse ist keine Zeit. Frames werden pro Ebene alphabetisch sortiert, damit möglichst viele zusammenfallen. Die Position von links nach rechts hat keine Bedeutung; ein Kasten links lief nicht früher als einer rechts.
  • Entscheidend ist die Breite. Sie zeigt den Anteil der Samples, in denen die Funktion auf dem Stack lag, einschließlich allem, was sie aufrief (inklusive Zeit). Der Teil eines Kastens, über dem nichts mehr liegt, ist die eigene Zeit der Funktion (Self Time).
  • Farben haben meist keine Bedeutung. Das Originalwerkzeug wählt zufällige warme Farben, nur um benachbarte Kästen zu unterscheiden. Manche Tools kodieren damit Codearten, etwa Kernel gegenüber User Space oder JIT-kompilierte gegenüber nativen Frames, oder heben Suchtreffer hervor.

Auf der Suche nach Optimierungszielen lohnt der Blick auf breite „Plateaus“ an der Oberkante: Ein breiter Kasten ohne etwas darüber ist eine Funktion, die selbst CPU verbraucht. Breite Kästen weiter unten zeigen, welche Codepfade dorthin führen.

Varianten: Icicle Graphs, Flame Charts und mehr

VarianteUnterschiedTypischer Einsatz
Icicle GraphGleiche Daten, umgedreht: Wurzel obenStandardlayout vieler Profiler, etwa der Weboberfläche von pprof und mehrerer Continuous Profiler
Flame ChartDie x-Achse ist die Zeit, Stacks werden nicht zusammengefasstBrowser-DevTools, Analyse eines einzelnen Requests oder Frames im Zeitverlauf
Differential Flame GraphFarben zeigen Veränderungen zwischen zwei Profilen, üblich: Rot für Zunahme, Blau für AbnahmeVergleich vor und nach einem Release
Off-CPU Flame GraphBreite ist Wartezeit (I/O, Locks, Sleep) statt CPU-ZeitLatenzprobleme, die keine CPU verbrauchen
Speicher-/Allokations-Flame-GraphBreite ist allozierter oder gehaltener Speicher in BytesAllokations-Hotspots, GC-Druck

Beispiel: Erzeugung unter Linux

Der klassische Ablauf mit Brendan Greggs FlameGraph-Skripten sampelt alle CPUs 30 Sekunden lang mit 99 Hz und erzeugt ein interaktives SVG:

perf record -F 99 -a -g -- sleep 30
perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > cpu.svg

99 statt 100 Hz verhindert, dass im Gleichtakt mit periodischen Timern gesampelt wird. Für Managed Runtimes empfiehlt sich ein Profiler, der deren Stacks versteht, etwa async-profiler für Java oder die eingebauten pprof-Endpunkte in Go. Sonst erscheinen JIT-kompilierte Frames womöglich nur als unaufgelöste Adressen.

Typische Fallstricke

  • Die x-Achse als Zeit lesen. Das ist die häufigste Fehlinterpretation. Wenn die Reihenfolge zählt, nutzen Sie einen Flame Chart oder einen Trace.
  • Fehlende Frames. Code ohne Frame Pointer, Inlining und fehlende Debug-Symbole führen zu abgeschnittenen oder „unknown“-Stacks.
  • Zu wenige Samples. 30 Sekunden auf einem fast untätigen Service liefern womöglich nur eine Handvoll Samples, die nicht repräsentativ sind.
  • Off-CPU-Zeit ignorieren. Ein langsamer Request, der auf die Datenbank wartet, taucht in einem CPU-Flame-Graph kaum auf. Kombinieren Sie Profile mit Spans, um Wartezeiten zu sehen.

Warum das für Observability wichtig ist

Metriken zeigen, dass CPU oder Latenz gestiegen sind, Traces zeigen, welcher Service und welche Operation langsamer wurden. Flame Graphs beantworten die nächste Frage: welcher Code in diesem Prozess verantwortlich ist. Mit Continuous Profiling in Produktion weist ein Flame Graph aus genau dem Zeitfenster eines Incidents oder ein Differential Flame Graph zwischen zwei Releases oft direkt auf einen regulären Ausdruck, eine Serialisierungsroutine oder einen umkämpften Lock.

Wie Obseria unterstützt

Das Continuous Profiling von Obseria erfasst CPU-, Allokations- und Lock-Profile aller Hosts mit unter 1 % Overhead und zeigt sie als Flame Graphs, gefiltert nach Service, Version und Zeitraum. Von einem langsamen Span im Distributed Tracing springen Sie direkt zum Profil desselben Prozesses im selben Zeitraum.

Häufig gestellte Fragen

Brendan Gregg entwickelte Flame Graphs 2011 bei der Performance-Analyse von MySQL und veröffentlichte die quelloffenen FlameGraph-Skripte, die sie aus der Ausgabe vieler Profiler erzeugen.

Nein. Die x-Achse steht für die Gesamtheit der Samples, pro Ebene alphabetisch sortiert, damit identische Stacks zusammenfallen. Brauchen Sie eine Zeitachse, nutzen Sie einen Flame Chart, wie ihn Browser-Entwicklertools bieten.

Beide zeigen dieselben Daten. Beim Flame Graph liegt die Wurzel unten und die Stacks wachsen nach oben, beim Icicle Graph ist es umgekehrt. Viele Profiling-Tools nutzen standardmäßig das Icicle-Layout, nennen es aber trotzdem Flame Graph.

In den ursprünglichen Flame Graphs werden Farben zufällig aus einer warmen Palette gewählt und dienen nur der Unterscheidung benachbarter Kästen. Manche Tools färben nach Codeart oder Paket, Differential Flame Graphs zeigen mit Farbe Zu- oder Abnahme zwischen zwei Profilen.

Setzen Sie das Wissen in die Praxis um

Testen Sie Obseria 14 Tage kostenlos, mit OpenTelemetry und ohne proprietäre Agenten.