Profilierung von C++-Code: Engpässe in der Praxis finden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

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_program


Starten 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.txt


Analysebeispiel



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 -pg kompiliert 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 report


Beispiel 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 elapsed


Wichtige Me

Blogs

Buchempfehlungen