ein Kapitel zurück                                           ein Kapitel weiter

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 zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf