Einleitung: Warum ist die Profilierung von C++-Code wichtig?
\nC++ ist eine der schnellsten Programmiersprachen, aber selbst damit kann man langsamen Code schreiben. Oft verschwenden Entwickler Stunden mit der Optimierung der falschen Programmteile, indem sie sich auf ihre Intuition verlassen. Profilierung ist ein wissenschaftlicher Ansatz zur Optimierung: Sie messen, wo das Programm die meiste Zeit verbringt, und verbessern gezielt diese Stellen.
\nFür Anfänger in der C++-Programmierung mag die Profilierung kompliziert erscheinen, aber die grundlegenden Werkzeuge sind an einem Abend erlernbar. In diesem Artikel behandeln wir drei beliebte Werkzeuge: gprof, perf und Valgrind, und lernen, ihre Ergebnisse zu interpretieren.
Was ist Profilierung und welche Methoden gibt es?
\nProfilierung ist das Sammeln von Daten über die Arbeitsweise eines Programms während seiner Ausführung. Es gibt zwei Hauptansätze:
\n- \n
- Instrumentierende Profilierung – Dem Programmcode werden spezielle "Sonden" hinzugefügt (z. B.
gprof). Nachteil: Verlangsamt die Programmausführung. \n - Sampling-Profilierung – In regelmäßigen Abständen wird "in das Programm geschaut" und aufgezeichnet, welche Funktion gerade ausgeführt wird (z. B.
perf). Verlangsamt das Programm kaum. \n
Es gibt auch Werkzeuge zur Suche nach Speicherlecks (Valgrind) und zur Cache-Analyse. Für den Anfang reicht es aus, gprof und perf zu beherrschen.
Werkzeug 1: gprof – der Klassiker der Profilierung
\ngprof ist ein integrierter Profiler für GCC. Er arbeitet in zwei Schritten: Datenerfassung und -analyse.
So verwenden Sie gprof
\nKompilieren Sie das Programm zunächst mit dem Flag -pg:
g++ -pg -o my_program my_program.cpp\nFühren Sie das Programm aus:
\n./my_program\nNach der Ausführung erscheint eine Datei gmon.out. Starten Sie nun gprof:
gprof my_program gmon.out > report.txt\nÖffnen Sie report.txt und sehen Sie sich die Tabelle an:
Flat profile:\nEach sample counts as 0.01 seconds.\n % cumulative self self total\n time seconds seconds calls ms/call ms/call name\n 60.00 0.06 0.06 10000 0.01 0.01 slow_function\n 30.00 0.09 0.03 5000 0.01 0.02 medium_function\n 10.00 0.10 0.01 1 10.00 10.00 main\nIn der Spalte % time wird angezeigt, wie viel Prozent der Zeit die Funktion beansprucht hat. In unserem Beispiel ist slow_function der Hauptkandidat für die Optimierung.
Tipp: Für kleine Programme ist gprof hervorragend geeignet. Bei großen Projekten kann es aufgrund von Compiler-Optimierungen ungenaue Daten liefern.
Werkzeug 2: perf – leistungsstarker Sampler für Linux
\nperf ist ein Profiler, der in den Linux-Kernel integriert ist. Er arbeitet nach der Sampling-Methode und verlangsamt das Programm kaum. Ideal für Produktionssysteme.
Grundlegende Verwendung von perf
\nKompilieren Sie das Programm mit Debug-Symbolen (Flag -g):
g++ -g -o my_program my_program.cpp\nStarten Sie die Profilierung:
\nperf record ./my_program\nNach Beendigung des Programms sehen Sie sich den Bericht an:
\nperf report\nSie sehen eine interaktive Oberfläche. Durch Klicken auf eine Funktion können Sie sehen, welche Codezeilen am häufigsten ausgeführt wurden. Beispielausgabe:
\nSamples: 1K of event 'cycles'\nEvent count (approx.): 250000000\nOverhead Command Shared Object Symbol\n 45.32% my_program my_program [.] slow_function\n 30.15% my_program my_program [.] medium_function\n 12.50% my_program libc-2.31.so [.] malloc\n 8.03% my_program my_program [.] main\nWichtig: perf benötigt Root-Rechte, um Kernel-Daten zu sammeln.