Are Perl's function calls slow?
The archetypal test of function call performance is the Ackermann Function. Go here to see the list of other languages that out-perform Perl for function call performance. Many of those are fully pre-compiled languages. Many are not.
For comparison purposes, look at straight forward implementations in Perl, with the same in Java.
Perl:
P:\test\MJD>ack1 9
Ack(3,9): 4093
78.843 83.671 0 0
Java:
P:\test\MJD>timethis "c:javac ackermann.java && java ackermann 9"
TimeThis : Command Line : c:javac ackermann.java && java ackermann 9
TimeThis : Start Time : Fri Sep 02 22:01:28 2005
Ack(3,9): 4093
TimeThis : Command Line : c:javac ackermann.java && java ackermann 9
TimeThis : Start Time : Fri Sep 02 22:01:28 2005
TimeThis : End Time : Fri Sep 02 22:01:29 2005
TimeThis : Elapsed Time : 00:00:01.031
I've included the compilation and runtime for Java to even the score a little. JIT was not enabled.
So 83.6 seconds for Perl, and 1.031 seconds for Java!
Conclusion: Perl's function calls are slow.
Is "Avoiding function calls because they are slow ... an absurd response to performance problems"?.
Anyone whom visited that Shootout page may have noticed that there are two supplementary versions of the Perl implementation of the Ackermann function, besides the one used in the main body of the tests.
These both run vastly more quickly than the main one
- Ack2.pl run 92x faster than the standard perl version
- Ack3.pl runs 474x faster.
How do they succeed in achieving this performance.
Ack2.pl uses (dominus's own) Memoize module. But how does this work?
Adding a couple of lines to the test case:
use Memoize;
memoize("Ack");
my $count = 0;
sub Ack {
$count++;
return $_[0] ? ($_[1] ? Ack($_[0]-1, Ack($_[0], $_[1]-1))
: Ack($_[0]-1, 1)) : $_[1]+1;
}
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my $ack = Ack(3, $NUM);
print "Ack(3,$NUM): $ack";
#print times;
print "Ack() called $count times";
shows exactly how it achieves it's performance:
P:\test\MJD>ack1 9
Ack(3,9): 4093
79.187 83.093 0 0
Ack() called 11,164,370 times
P:\test\MJD>ack2 9
Ack(3,9): 4093
0.046000
Ack() called 12,294 times
The performance is achieved by avoiding making function calls! 12,294 -v- 11,164,370
And how does Ack3.pl achieve it's further gain in performance?
By in-lining the caching and thereby further reducing the number of function calls, by avoiding those that Memoize wraps around the memoized function!
Indeed, a substantial portion of dominus' book, High Order Perl deals with the very subject of eliminating recursion (p.229–53, 348 (from the index)).
Conclusion: Avoiding function calls as a means of improving performance *is not* "...an absurd response..." to poor performance.
Is "... the right response ... to try to fix the implementation" a feasible, practical suggestion?
The number of people that have the required knowledge and expertise to dive into the perl sources to make this kind of change probably number in the low 10s.
That's not to say that there isn't the possibility of scope for improvements. If you dump the assembler generated by an Inline C or XS function call and look at the number of times _Perl_get_context() is called in the prolog and epilog, there certainly seems to be the potential for some reduction. Of course, it may well be that a good optimising compiler succeeds in reducing some of the duplication, but that will vary from compiler to compiler and platform to platform.
But a bunch of very clever guys have spent a good few years tuning the performance of Perl 5, and the idea that your average PerlMonk is going to do better than them any time soon, is .... (I'll leave the adjective to the individual reader to fill in).
The idea that your average Perlmonk is likely to be able to go this route is overly optimistic at best. At worst, it is completely specious.
Does my characterisation (of dominus' characterisation of the very techniques that his own module and book exploit as "absurd"), as "academic hot air" constitute a grievous insult?
Others will draw their own conclusions, but for my part, I think that the idea that your average PerlMonk could adopt the suggestion "to improve the implementation" *is* academic.
In that regard, dominus' voicing that suggestion, given his knowledge, expertise and history of exploiting the very technique he decried, *is* "hot air".
Can a factual statement, regardless of the wording, be "an insult"?