Olf   Projekte   Kunst   Software   Bio   Links   Private   Mail
  english version

 | Up |

FuncSub

Während ich nach einer Möglichkeit gesucht habe, die Performance von Geniustrader zu verbessern, ist mir aufgefallen, dass sehr viel Zeit für diverse Funktionsaufrufe draufgeht, deren Funktion lediglich darin besteht, einen einzelnen Wert zurückzugeben.

Dies ist das Resultat das streng objektorientierten Programmierweise, die Geniustrader zu Grunde liegt. Diese ist zwar sehr sinnvoll, um den Code lesbar zu halten, führt jedoch auch dazu, dass durch die vielen Funktionsaufrufe die Performance leidet. Hier ist das Ergebnis eines etwas umfangreicheren Backtests mit dem DProf-Module analysiert (dabei wude das DirtyKill-Modul verwendet, so dass die Carp::Datum-Aufrufe eliminiert sind):

Tested ... ok in 79 seconds
Total Elapsed Time = 20.27753 Seconds
         User Time = 14.72753 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 74.2   10.92  7.779 157523   0.0000 0.0000  GT::CacheValues::is_available
 44.9   6.620 11.841 194946   0.0000 0.0001  GT::ArgsTree::get_arg_values
 38.8   5.719  3.816 952019   0.0000 0.0000  GT::Registry::get_name
 37.5   5.529  2.043 174341   0.0000 0.0000  GT::Calculator::indicators
 36.8   5.426  6.158 506514   0.0000 0.0000  GT::Indicators::Prices::calculate
 22.0   3.246  3.968 201000   0.0000 0.0000  GT::Indicators::Generic::Eval::cal
                                             culate
 21.6   3.186  4.358  13517   0.0002 0.0003  GT::Dependency::dependencies_are_a
                                             vailable
 18.7   2.764 17.552   8002   0.0003 0.0022  GT::Indicators::calculate_interval
 9.36   1.379  7.435 163164   0.0000 0.0000  GT::Indicators::__ANON__
 9.23   1.359  3.472  40023   0.0000 0.0001  GT::Dependency::days_required
 9.17   1.350  0.962 193972   0.0000 0.0000  GT::CacheValues::get
 7.99   1.177 24.249   2502   0.0005 0.0097  GT::Indicators::SMA::calculate
 6.65   0.980  0.953  13743   0.0001 0.0001  Carp::Datum::DTRACE
 5.70   0.839  0.847    557   0.0015 0.0015  Carp::Datum::Strip::strip

Man kann leicht sehen, dass ein grosser Teil der Laufzeit z.b. von der Funktion GT::CacheValues::is_available verbraucht wird. Diese gibt letztlich nur einen Wert zur¨ck, nämlich ob ein Hashelement definiert ist oder nicht. Dadurch, dass diese Funktion ca. 160.000 Mal aufgerufen wird, entsteht ein unnötiger Overhead.

Nachdem Download des Skriptes, sollte man das GT-Verzeichnis nach /tmp kopieren und das Skript auf alle Dateien wie folgt anwenden:

for i in $(find /tmp/GT -name '*.pm')
do
   cp $i /tmp/funcsub.tmp
   perl funcsub.pl /tmp/funcsub.tmp > $i 
done;

Nun ist noch ein use lib '/tmp';-Statement in das auszuführende Programm einzufügen und schon sieht die Performance so aus (dabei ist der Aufruf zu DirtyKill - im Gegensatz zu oben nicht in der Laufzeit enthalten):

Tested ... ok in 41 seconds
Total Elapsed Time = 27.65204 Seconds
         User Time = 28.04077 Seconds
Exclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c  Name
 18.5   5.199  9.895 194946   0.0000 0.0001  GT::ArgsTree::get_arg_values
 13.3   3.750  3.305 506514   0.0000 0.0000  GT::Indicators::Prices::calculate
 8.56   2.399  2.520 201000   0.0000 0.0000  GT::Indicators::Generic::Eval::cal
                                             culate
 7.91   2.219  2.416  13517   0.0002 0.0002  GT::Dependency::dependencies_are_a
                                             vailable
 6.60   1.852 10.603   8002   0.0002 0.0013  GT::Indicators::calculate_interval
 5.53   1.550  1.356 193972   0.0000 0.0000  GT::CacheValues::get
 5.10   1.430  6.421 163164   0.0000 0.0000  GT::Indicators::__ANON__
 4.28   1.199  4.346  40023   0.0000 0.0001  GT::Dependency::days_required
 3.71   1.040 17.051   2502   0.0004 0.0068  GT::Indicators::SMA::calculate
 3.21   0.899 65.776   6002   0.0001 0.0110  GT::Dependency::compute_dependenci
                                             es
 2.96   0.830  0.671 158817   0.0000 0.0000  GT::ArgsTree::get_nb_args
 2.57   0.720  0.706  13743   0.0001 0.0001  Carp::Datum::DTRACE
 2.50   0.700  0.640  59542   0.0000 0.0000  GT::Dependency::get_indicator_depe
                                             ndencies

Wie unschwer zu erkennen ist, hat sich die Performance um fast 50% verbessert. ...und es können sicherlich noch weitere Funktionen auf diese Art und Weise ersetzt werden (Feedback ist wie immer willkommen).

Es gibt jedoch zu beachten, dass das Skript nur auf der Basis von regulären Ausdr¨cken arbeitet und deshalb leicht Fehler erzeugen kann. Für die Zukunft wäre es sicher sinnvoll, z.B. auf der Basis des Modules B::Deparse einen echten Parser zu schreiben, der zum einen in der Lage ist, selbst nach Funktionen zu suchen und zum anderen z.B. den Typ des aufrufenden Objects berücksichtigt.

Die Funktionalität dieses Moduls ist nun in das Modul OptimizeGT.pm integriert. Dieses ist mittlerweile Teil der offiziellen Distribution.

Download von funcsub.pl


 Fresh stuff  

Wüstenrennmäuse

Weihnachtsgebäck

Tim der Mauersegler

Trading Tagebuch V0.10

 
 Features  

Impressum

Feedback

Olf's Such-Seite

eCards

Geniustrader

 
 News  

Bilder aus der Wildnis

Zurück von der Insel...

Lebenszeichen

Mehr Bilder, mehr Besucher, mehr Rezepte...

Wilkommen in 2005!

Weitere News...

 
© 2004 Oliver Bossert