[ICON] Wieviel Zeit verbraucht ein Programm mit Abhängen in welchen Zeilen?

  • Hallo zusammen,


    heute habe ich durch Zufall etwas ganz Interessantes herausgefunden. Vielleicht kann es jemand gebrauchen.


    Eine Spezialität von Icon besteht im Einsatz von Programm-Monitoring und ähnlichen Anwendungen.



    Der Hintergrund besteht darin herauszufinden, welcher Anteil der Laufzeit eines Programms mit Verbringen in welchen Zeilen entfällt. Als Nebenprodukt erhält man dann auch eine Antwort der Code-Abdeckung, d.h. wird jede Zeile eines Programm mal durchlaufen - oder gibt es (wenn ein paar Zeilen nicht durchlaufen werden) auch noch nicht entdeckte Bugs.
    Als Haupterkenntnis weiß man aber, mit was die meiste Rechenzeit verbraten wird und man kann hier ggf. gezielt optimieren.


    1. Beispiel-Programm
    Nehmen wir ein kleines Beispiel-Programm:


    Was mir spontan einfällt, ein Programm, das die Fakultäten von 1, 10, 100, 1000 und 10000 ausgibt. Hierbei weiß ich, dass das Rechnen selber eigentlich ganz flott geht. Aber das Darstellen von 10000! mit mehreren Tausend Stellen als Ganzzahl ohne Informationsverlust dauert - richtig heftig - lange!


    Wen es interessiert: Die Technik dahinter heißt LIA (Large Integer Arithmetik), wonach Ganzzahlen in Icon beliebig groß werden können und in der Größe eigentlich nur durch den Arbeitsspeicher sowie bei der Ausgabe durch die Geduld des Anwenders begrenzt werden. Die Geduld ist wohl die kleinere Grenze.


    Das Programm würde z.B. so aussehen:



    2. Testlauf ohne Ausgabe
    Das Programm lassen wir mal laufen.


    Ohne dass man eine Verzögerung zwischen den einzelnen Zeilen bemerkt, wird Folgendes ausgegeben:

    Code
    1. 1! =
    2. 10! =
    3. 100! =
    4. 1000! =
    5. 10000! =


    3. Testlauf mit Ausgabe
    Dann lassen wir das Programm einmal mit Ausgabe laufen:


    4. Zwischenerkenntnis
    Die ersten drei Zeilen kommen sofort, die vierte Zeile kurz danach - und die letzte Zeile dauert... aber immerhin kommt dann auch das - übrigens korrekte - Ergebnis. Das lässt sich über vollständige Induktion zeigen und darüber dass alle N! / N = (N-1)! gilt und sich diese Gleichheit bis Fakultätetn zurückführen lassen, die man selber berechnen kann. Meinetwegen auch bis 3!/3 = 6/3 = 2 = 2! Aber egal.


    Die Programme laufen also schon mal.


    5. MAGIE!
    Jetzt sind ein paar Tricksereien erforderlich.


    5.1 Anlegen einer Umgebungsvariablen

    Code
    1. ICONPROFILE="/home/pi/icon9_51/bin/profiler
    2. export ICONPROFILE


    In die angegebene Datei wird ein spezielles Profil eines Programmablaufs abgelegt. Wie die Datei aussieht, sehen wir dann auch gleich.


    5.2 Programm iprofl
    Dann kopieren wir das Programm [font="Courier New"]iprofl.icn[/font] aus der dem Verzeichnis [font="Courier New"]progs[/font] der [font="Courier New"]IPL[/font] (Icon Program Library) in das Icon-Arbeitsverzeichnis [font="Courier New"]/home/pi/icon9_51/bin[/font] und compilieren es dort.
    Wir wechseln in das Arbeitsverzeichnis:

    Code
    1. cd /home/pi/icon9_51/bin


    6. Programmlauf ohne Ausgabe
    Dann lassen wir das Programm mal mit ganz speziellen Optionen compilieren und laufen:

    Code
    1. icont -p fak_test -x


    Die Option [font="Courier New"]-p[/font] weist den Icon-Compiler an, ein solches Profil zu erzeugen, [font="Courier New"]fak_test[/font] ist der Name des Programms und [font="Courier New"]-x[/font] weist das System an, das Programm nach dem Compilieren auch gleich zu starten.


    Anmerkung: Wer sowas öfters machen will, kann diese Parameter auch in Geany verewigen (s. dazu Icon Tutorial Teil 2).


    7. Die Datei [font="Courier New"]profiler[/font]
    Was in die Datei [font="Courier New"]profiler[/font] geschrieben wurde, erfahren wir nach Eingabe von[/b]

    Code
    1. cat profiler


    In der Datei [font="Courier New"]/home/pi/icon9_51/bin/profiler steht jetzt[/font]:


    Diese Zeilen sagen uns Folgendes:
    Eine relative Zeit verweilt die Ausführung in diesen Zeilen des angegebenen Programms. Hier können, wenn andere Dateien eingebunden wurden, auch deren Dateinamen stehen. Das mag zunächst verwirrend sein - aber fast alle wirklichen Anwendungen bestehen aus zahlreichen Quellcode-Dateien, die ineinander eingebunden oder auch mit Programmbibliotheken zusammengebunden werden. In der zweiten Spalte steht die Anzahl, wie oft diese Zeile durchlaufen wurde.
    Hieraus können wir erkennen, dass die meiste Rechenzeit in Zeile 4 verbraten wurde, weil hier die einzige Zeile mit einer nennenswerten Verweildauer und alles überragenden Häufigkeit versehen ist.


    8. Das Programm [font="Courier New"]iprofl[/font]
    Dann lassen wir mal das Programm [font="Courier New"]iprofl[/font] laufen

    Code
    1. iprofl profiler


    Dieses Programm liest die Datei profiler aus und ermittelt aus dem Produkt von Durchlaufzahl und Verweildauer die relative Verweildauer (ausgedrückt in Promille-Werten - Prosit, wer was anderes dabei denkt!).


    Dann erhalten wir als Ausgabe:


    Das Ergebnis ist beeindruckend: 999 Promille der gesamten Rechenzeit entfällt auf die angegebene Programmzeile - die Multiplikationszeile. Das Ergebnis überrascht aber nicht wirklich.



    9. Programmlauf mit Ausgabe
    Jetzt wiederholen wir das Ganze mit Ausgabe des Rechenergebnisses:

    Code
    1. icont -p fak_test -x


    Ausgabe:



    10. Die Datei [font="Courier New"]profiler[/font]
    Die Datei [font="Courier New"]profiler[/font] enthält nach Eingabe von

    Code
    1. cat profiler


    den Inhalt


    wonach die Ausgabe des Ergebnisses für sich genommen sehr viel Zeit benötigt - aber eben auch nur 5 mal durchlaufen wird.
    Die relative Verweildauer der Multiplikationszeile 4 fällt jetzt deutlich geringer ins Gewicht.


    11. Das Programm [font="Courier New"]iprofl[/font]
    Und jetzt kommt die Überraschung, nämlich nach Eingabe von

    Code
    1. iprofl profiler


    erfolgt die finale Ausgabe von


    Demnach werden 12 Promille der Rechenzeit mit der Multiplikation, und 988 Promille mit der Ausgabe verbracht.



    12. Beispiel mit unvollständiger Code-Abdeckung
    Wir setzen in der Routine fak() hinter fail folgende Zeile ein:

    Code
    1. oiweanrv()


    und compilieren diese Programm-Version.


    Wer von anderen Programmiersprachen kommt, wird sich vielleicht wundern, dass hier keine Fehlermeldung kommt. Das liegt u.a. daran, dass es in Icon möglich ist, Namen von Variablen und Prozeduren während der Laufzeit zu setzen. Daher macht eine Fehlermeldung zur Compile-Zeit keinen Sinn, denn es könnte ja sein, dass dieser Prozedur während der Laufzeit noch etwas an Bedeutung zugewiesen wird - auch wenn es sich in 99,9% der Fälle um pure Tippfehler handeln wird.
    Also: Diese Funktion gibt es nicht im ausführbaren Programm und dieser Funktion wird auch nicht zugewiesen, was mal aufgerufen werden könnte.


    Die Funkion fak() kehrt entweder mit einem Ergebnis zurück oder scheitert (fail). Die Funktion [font="Courier New"]oiweanrv()[/font] wird niemals aufgerufen werden. Eine Fehlermeldung kann es nie geben.


    Wir lassen die drei Schritte ablaufen

    Code
    1. icont -p kill_test -x
    2. cat profiler
    3. iprofl profiler


    und erhalten



    Hier erkennt man eindeutig, dass [font="Courier New"]fail[/font] niemals durchgeführt wurde (das liegt am Parameter beim Aufruf von [font="Courier New"]fak()[/font]) - und [font="Courier New"]oiweanrv()[/font] erwartungsgemäß ebenfalls nie erreicht wurde. Wenn [font="Courier New"]fail[/font] nicht im Code stehen würde, dann würde bei Aufruf von [font="Courier New"]fak(0)[/font] ein Laufzeitfehler erfolgen. Das heißt, mit diesem Tool kann man sich einen Überblick verschaffen, wo im Code noch potentielle Laufzeitfehler verborgen sein könnten. Denn eine Programmzeile, die schon über 10000 mal durchlaufen wurde, wird wohl fehlerfrei sein.



    Beste Grüße


    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    • Icon-Tutorials (IDE: Geany) - GPIO-Library - µController-Programmierung in Icon! - ser. Devices - kein Support per PM / Konversation

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Edited 2 times, last by Andreas ().