Ein Flame Graph stellt zu einem Programm (z. B. dem FreeBSD‑Kernel) die Funktionsaufrufe dar und wie lange es in einer bestimmten Funktion gebraucht hat.
Der Graph zeigt Namen von Funktionen in Kästchen übereinander an, wenn die untere die obere aufgerufen hat. Über die Breite der Kästchen zeigt der Graph, wie viel Zeit die Funktion eingenommen hat. Durch Klicken auf ein Kästchen lässt sich in dem Graph zoomen.
Brendan Gregg beschreibt Flame Graphs ausführlich auf seiner Webseite: https://www.brendangregg.com/flamegraphs.html.
Zum Erstellen eines Flame Graphs werden Daten eines Profilers benötigt. Bei FreeBSD können das z. B. DTrace oder pmcstat liefern. Hier am Beispiel von pmcstat gezeigt.
Es wird ein CPU Performance Counter verwendet. Dafür muss erst das hwpmc Modul geladen werden.
kldload -n hwpmc
Nun kann das Programm gestartet werden, zu dessen Ausführung ein Flame Graph erstellt werden soll. Das kann z. B. iperf3 sein.
iperf3 -t 20 -c 192.168.11.3 > /dev/null &
Während das Programm läuft, muss man pmcstat starten.
pmcstat -S cpu_clk_unhalted.thread_p -O cksum.pmc sleep 10
Der Aufruf nutzt den CPU Performance Counter cpu_clk_unhalted.thread_p, misst für 10 Sekunden und schreibt die Daten im Binärformat in die Datei cksum.pmc. Welche CPU Performance Counter verwendet werden muss, hängt von der CPU ab, siehe cpu_performance_counter.
Nach der Messung müssen die Daten aufbereitet werden.
pmcstat -R cksum.pmc -z100 -G cksum.graph
Der Aufruf schreibt die Callchain-Informationen in die Datei cksum.graph.
Zur Visualisierung in einem Flame Graph müssen abschließend zwei Perl-Skripte ausgeführt werden, die sich in diesem GitHub-Repository befinden: https://github.com/brendangregg/flamegraph.
git clone https://github.com/brendangregg/flamegraph flamegraph/stackcollapse-pmc.pl cksum.graph | flamegraph/flamegraph.pl > cksum.graph.svg
Die SVG-Datei kann in einem Browser geöffnet werden. Die folgende Grafik zeigt ein Flame Graph.
Die Namen des relevanten Performance Counter unterscheidert sich je nach CPU-Hersteller.
ls_not_halted_cyccpu_clk_unhalted.thread_pCPU_CYCLESDie Auflistung stammt von Olivier Cochard-Labbé, der die auf seiner Webseite zeigt: https://bsdrp.net/documentation/technical_docs/performance#pmcstat.
Nicht jede CPU bietet die gleiche Menge an Performance Counter. Eine Liste der verfügbaren Performance Counter lässt sich mit pmcstat ausgeben.
kldload -n hwpmc pmcstat -L ... br_misp_retired.taken cpu_clk_thread_unhalted.one_thread_active cpu_clk_thread_unhalted.ref_xclk cpu_clk_thread_unhalted.ref_xclk_any cpu_clk_unhalted.one_thread_active cpu_clk_unhalted.ref_tsc cpu_clk_unhalted.ref_xclk cpu_clk_unhalted.ref_xclk_any cpu_clk_unhalted.thread cpu_clk_unhalted.thread_any cpu_clk_unhalted.thread_p cpu_clk_unhalted.thread_p_any cycle_activity.cycles_l1d_pending ...
Das folgende Skript erstellt ein Flame Graph zu der Ausführung von iperf3. Es lässt die ersten 5 Sekunden aus, um die Effekte beim Start einer Verbindung außen vor zu lassen.
kldload -n hwpmc file=$1 flamegraph=/home/msvoelker/FlameGraph iperf3 -t 20 -c 192.168.11.3 > /dev/null & sleep 5 pmcstat -S cpu_clk_unhalted.thread_p -O $file.pmc sleep 10 pmcstat -R $file.pmc -z100 -G $file.graph $flamegraph/stackcollapse-pmc.pl $file.graph | $flamegraph/flamegraph.pl > $file.graph.svg