![ein Kapitel weiter](../weiter.gif)
Für vielen wird die Laufzeitmessung in dem Kapitel zuvor ausreichen.
Was aber wenn sie einzelnen Funktionen oder Codeabschnitte Ihres
Programmes messen wollen?
Sie werden in diesem Kapitel erfahren wie es mögich ist die Perfomance
Ihres Codes zu tunen. Um den Code zu tunen ist ein vorhergehendes Profiling
notwendig.
Der Begriff "Profiling" bedeutet nichts anderes als eine Laufzeitmessung
allgemeiner Art. Es gibt mehrere Profiler. Wir verwenden hier aber denn
auf vielen Systemen vorhanden GNU-Profiler gprof. Sie finden diesen unter
www.gnu.org
In folgenden 3 Schritten wollen wir das Profiling verwenden......
- Das Programm übersetzen mit der Instrumentierung zum Profiling
- Programm laufen lassen und das Profile erstellen
- Profile auswerten
Wir verwenden hier einen simplen und sinnlose Code. Einfaches Beispiel.
Sie wollen eine for-Schleife 1000000000 mal durchlaufen lassen.
/*Download:loop.c*/
#include <stdio.h>
void for_schleife_increment(void)
{
long i;
for(i=0;i<1000000000; i++);
}
void for_schleife_decrement(void)
{
long i;
for(i=1000000000; i>0; i--);
}
int main(int argc, char **argv)
{
for_schleife_increment();
for_schleife_decrement();
return 0;
}
|
Nun wollen wir das Programm mit der Instrumentierung zum Profiling
übersetzen...
gcc -pg schleife.c
Der Schalter -pg bereitet für uns das Profiling vor und binden die
Bibliothek libgmon.a mit ein.
Nun befindet sich in Ihrem Verzeichnis eine Datei Namens "a.out"
Führen sie diese aus wie einen normalen Programmaufruf....
./a.out
Je nach Rechner kann das ganze jetzt ein bißchen dauern. Bei über 30 sec.
Rufen sie nun...
ls-l
...auf und sie finden in Ihrem Verzeichnis ein Datei Namens gmon.out
Da es sich dabei um ein Binärdatei handelt können wir damit noch nichts
anfangen.
Nun kommt der Grosse Moment unseres Profilers gprof...
gprof a.out > profile.txt
Die Ausgabe liefert Ihnen nun die Textdatei profile.txt mit allen Zeitmessungen.
Wichtig!! Ohne der Datei gmon.out funktioniert der Aufruf von gprof nicht!!
Nun haben sie eine Datei Namens Profile mit 2 längeren Abschnitten.
Zuerst haben wir das Flat Profile mit folgenden Zeiten........
% cumulative self self total
time seconds seconds calls ms/call ms/call name
50.03 15.56 15.56 1 15560.00 15560.00 for_schleife_decrement
49.97 31.10 15.54 1 15540.00 15540.00 for_schleife_increment
Hier sehen sie die Gesamtlaufzeit unseres Programms und deren einzelnen
Funktionen. Hierzu neun ein Erklärung der Spalten der Reihe nach:
- %time = Anteil der Gesamtlaufzeit in Prozent. Beide Funktionen verbrauchen
in etwa 50% der Zeit. Also kein nennenswerter Unterschied.
- cumulative seconds = Akutuelle Verbrauchte Laufzeit in dieser Funktion und allen
ander nach oben Verlaufenden Funktionen. Also endete bei 15.56 Sekunden
die Funktion for_schleife_decrement und begann dabei die Funktion
for_schleife_increment. Dies endete in Sekunde 31.1, und somit auch das
ganze Programm.
- self seconds = Laufzeit der Funktion alleine. Daraus ergeben sich auch die
Prozentwerte am Anfang
- calls = Anzahl der Aufrufe diesr Funktion
- self ms/call = Duchschnittliche Zeit pro Aufruf dieser Funktion in Mikrosek.
- total ms/call = Durchnittlich Zeit in allen Aufrufen diesr Funktion in Mikrosek.
- name = Name der Funktion
Im zweiten Abschnitt finden sie Anschließend sogenannte Call graph
Bei mir Ergaben sich dabei folgende Messungen........
index % time self children called name
<spontaneous>
[1] 100.0 0.00 31.10 main [1]
15.56 0.00 1/1 for_schleife_decrement [2]
15.54 0.00 1/1 for_schleife_increment [3]
-----------------------------------------------
15.56 0.00 1/1 main [1]
[2] 50.0 15.56 0.00 1 for_schleife_decrement [2]
-----------------------------------------------
15.54 0.00 1/1 main [1]
[3] 50.0 15.54 0.00 1 for_schleife_increment [3]
-----------------------------------------------
Auch hierzu die Bedeutung der einzelnen Spalten......
- index = Nummer zur Orientierung
- %time = Verbrauchte Zeit in Prozent
- self = Laufzeit in Sekunden der Funktion
- children = Tatsächliche Laufzeit die in dieser Funktion verbracht wurden.
Logischerweise läuft das komplette Programm in der main-Funktion ab.
- called = Erste Zahl sind die Aufrufe an die Bezugsfunktion. Die Zweite Zahl
sind die Aufrufe der Bezugsfunktion insgesammt. In Bezug auf unser Programm...
[1] 100.0 0.00 31.10 main [1]
15.56 0.00 1/1 for_schleife_decrement [2]
15.54 0.00 1/1 for_schleife_increment [3]
Die Funktion main [1] hat die Funktion for_schleife_decrement 1 mal aufgerufen
von insgeamt 1 Aufruf. Weiterhin hat unsere Funktion main die Funktion
for_schleife_increment 1 mal aufgerufen von insgesamt 1 Aufruf.
15.56 0.00 1/1 main [1]
[2] 50.0 15.56 0.00 1 for_schleife_decrement [2]
Die Funktion for_schleife_decrement [2] wurde von der Funktion main 1 mal
von 1 insgesamt 1 mal Aufgerufen.
Insgesamt wurde die Funktion for_schleife_decrement [2] 1 mal Aufgerufen.
usw.
Diese Beispiel das wir hier verwendet haben war natürlich Sinnlos. Wir werden
diese Möglichkeit der Laufzeitmessung aber noch Effektiver einsetzen wenn wir
zu den Alogrithmen kommen. Beispielsweise Sortier-Alorithmen. Mit Hilfe
des Tk-Modules oder dem GD-Modules wollen wir das ganze dann auch noch mit
Grafischer Ausgabe belegen.
![ein Kapitel weiter](../weiter.gif)
© 2001,2002 Jürgen Wolf
|