FuncSub
While I was trying to enhance the performance for Geniustrader I noticed that
much time is used for various function calls that simply deliver a single value.
This results from the strict objectorientated styls in which GeniusTrader is written.
This is quite useful to make the code readable but it leads also to a very bad performance.
I show you here the result of a somewhat larger backtest, analyzed with the DProf-module
(the DirtyKill-module is applied so that the Carp::Datum calls are eliminated):
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
As one can clearly see, a large part of the runtime is used for the function
GT::CacheValues::is_available. This function only returns one value (if
a hashelement is defined or not). Because this function is called approx. 160,000
times this leads to a needlessy overhead.
After downloading the script you should copy your GT-directory to /tmp and apply the
script on all files:
for i in $(find /tmp/GT -name '*.pm')
do
cp $i /tmp/funcsub.tmp
perl funcsub.pl /tmp/funcsub.tmp > $i
done;
Now simply insert a use lib '/tmp';-statement in the program that you want
to execute and you'll get a much better performance (the call to DirtyKill is - in contrast
to the listing above not contained in the list):
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
The performance is enhanced by nearly 50% ... and I'm sure there are some more functions
that can be replaced like this (as always feedback is very welcome).
But you have to pay attention that the script is based on regular expressions only -
thus an error can occur quite easily. For the future it would be better to use e.g.
B::Deparse to write a real parset that is on the one hand able to find short functions
by itself and on the other hand makes it possible to consider the type of the calling
object.
The functionality of this module is now integrated in the module
OptimizeGT.pm that is now also part of the official distribution.
Download von funcsub.pl
|