Einleitung: Warum C++-Code profilieren?
Optimierung ohne Messungen ist reine Spekulation. Selbst erfahrene Entwickler irren sich oft bei der Annahme, welcher Codeabschnitt am langsamsten ist. Die Profilierung ist die einzige wissenschaftliche Methode, um die Frage zu beantworten: „Wo genau verbringt das Programm die meiste Zeit?“.
In diesem Artikel behandeln wir praktische Werkzeuge zur Profilierung von C++-Code unter Linux: gprof, perf und Valgrind (Callgrind). Sie erfahren, wie Sie Profiler starten, deren Berichte interpretieren und echte Engpässe finden.
1. Profilierung mit gprof
Code-Vorbereitung
gprof ist der einfachste und am leichtesten zugängliche Profiler. Für seine Nutzung muss das Programm mit dem Flag -pg kompiliert werden:
g++ -pg -O2 main.cpp -o my_programStarten Sie das Programm. Es wird etwas langsamer als gewöhnlich ausgeführt, erstellt aber die Datei gmon.out mit den Profilierungsdaten. Anschließend starten Sie gprof:
./my_programgprof my_program gmon.out > report.txtAnalysebeispiel
Betrachten wir ein einfaches Programm mit zwei Funktionen:
#include <iostream>#include <cmath>
void slowFunction() { double sum = 0.0; for (int i = 0; i < 100000000; ++i) { sum += std::sin(i) * std::cos(i); } std::cout << "Sum: " << sum << std::endl;}
void fastFunction() { int count = 0; for (int i = 0; i < 1000; ++i) { for (int j = 0; j < 1000; ++j) { count += (i * j) % 3; } } std::cout << "Count: " << count << std::endl;}
int main() { slowFunction(); fastFunction(); return 0;}Nach dem Start von gprof sehen wir im Bericht eine Tabelle mit der Ausführungszeit jeder Funktion:
Flat profile:
Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 99.0 1.98 1.98 1 1980.0 1980.0 slowFunction() 1.0 0.02 0.02 1 20.0 20.0 fastFunction()Die Schlussfolgerung ist offensichtlich: slowFunction() benötigt 99% der Zeit. Der Engpass sind die Aufrufe der trigonometrischen Funktionen sin und cos in der Schleife.
Einschränkungen von gprof
- Funktioniert nur mit Programmen, die mit
-pgkompiliert wurden - Zeigt keine Zeit in Inline-Funktionen an
- Nicht geeignet für Multithread-Anwendungen (ohne zusätzliche Einstellungen)
2. Profilierung mit perf (Linux)
Grundlegender Start
perf ist ein leistungsstarkes Werkzeug zur Profilierung auf Kernel-Ebene. Es erfordert keine Neukompilierung des Programms und funktioniert mit beliebigen Binärdateien (sogar mit Optimierung -O3):
# Installation (falls nicht vorhanden)sudo apt install linux-tools-common linux-tools-generic
# Profilierung mit Zählung der CPU-Takteperf stat ./my_program
# Aufzeichnung von Ereignissen für detaillierte Analyseperf record ./my_programperf reportBeispiel mit perf stat
Für dasselbe Programm zeigt perf stat Folgendes an:
Performance counter stats for './my_program':
1,987.45 msec task-clock # 1.000 CPUs utilized 10 context-switches # 5.028 /sec 0 cpu-migrations # 0.000 /sec 105 page-faults # 52.832 /sec 5,234,567,890 cycles # 2.634 GHz 9,876,543,210 instructions # 1.89 insn per cycle 1,234,567,890 branches # 621.234 M/sec 10,000,000 branch-misses # 0.81% of all branches
1.987456789 seconds time elapsedWichtige Me