Looks like it may be time to investigate things further. A method cache is probably the next thing in line to do.
I didn't see a benchmark for method lookup and calling, so I modified a copy of fib to bounce back and forth between a class and its parent. Patch attached. My optimized parrot ran it a factor of 2x slower than my perls, 3x than my ruby, with my pythons in between. Unoptimized was just a bit worse. (However, caveat, my optimized parrot doesn't pass make test.) A quick look at a profile (*** always a dangerous practice ***) seemed _vaguely_ like half method calls, and half memory management. With method calls split between lookup (spent in hash), and creating return continuation pmcs. I thought it curious 1/10+ of time seemed spent under Parrot_set_s_sc, when there's nary a string to be seen. Method names? I wonder if find_global might be happier with a simpler hash than hash. Especially if this is where the string copies are coming from. The 1/4 time spent creating continuations also seemed notable. So a quick, and thus no doubt wrong, interpretation might be that method calling is leaning hard on memory, which is then leaning hard on time. Maybe. Mitchell
--- nonexistent Tue Mar 16 22:18:01 2004 +++ ./examples/benchmarks/method1.rb Tue Mar 16 18:51:38 2004 @@ -0,0 +1,25 @@ +#! ruby + +class A + def fib(n) + return n if (n < 2) + return fibA(n - 1) + fibB(n - 2) + end + def fibA(n) + return n if (n < 2) + return fib(n - 1) + fibB(n - 2) + end +end + +class B < A + def fibB(n) + return n if (n < 2) + return fib(n - 1) + fibA(n - 2) + end +end + +b = B.new + +N = Integer( ARGV.shift || 24 ) + +puts "fib(#{N}) = #{ b.fib(N) }" --- nonexistent Tue Mar 16 22:18:01 2004 +++ ./examples/benchmarks/method1.pl Tue Mar 16 18:41:47 2004 @@ -0,0 +1,33 @@ +use strict; + +package A; +sub fib { + my $self = shift; + my $n = shift; + return $n if ($n < 2); + return $self->fibA($n-1) + $self->fibB($n-2); +} +sub fibA { + my $self = shift; + my $n = shift; + return $n if ($n < 2); + return $self->fib($n-1) + $self->fibB($n-2); +} +package B; [EMAIL PROTECTED]::ISA=qw(A); +sub new { bless {}, $_[0] } +sub fibB { + my $self = shift; + my $n = shift; + return $n if ($n < 2); + return $self->fib($n-1) + $self->fibA($n-2); +} + +package main; + +my $N = shift || 24; + +my $b = B->new(); + +print "fib($N) = ", $b->fib($N), "\n"; + --- nonexistent Tue Mar 16 22:18:01 2004 +++ ./examples/benchmarks/method1.imc Tue Mar 16 19:14:44 2004 @@ -0,0 +1,106 @@ + +.pcc_sub _main prototyped + .param pmc argv + .sym int argc + argc = argv + .sym int N + N = 24 + if argc <= 1 goto noarg + $S0 = argv[1] + N = $S0 +noarg: + .sym float start + time start + + .local pmc A + .local pmc B + .local pmc b + + newclass A, "A" + subclass B, A, "B" + + find_type I0, "B" + new b, I0 + + .sym int r + r = b.fib(N) + + .sym float fin + time fin + print "fib(" + print N + print ") = " + print r + print " " + sub fin, start + print fin + print "s\n" + end +.end + +.namespace ["A"] + +.sub fib method + .param int n + if n >= 2 goto rec + .pcc_begin_return + .return n + .pcc_end_return +rec: + .sym int n1 + .sym int n2 + .sym int r1 + .sym int r2 + n1 = n - 1 + n2 = n - 2 + r1 = self.fibA(n1) + r2 = self.fibB(n2) + n = r1 + r2 + .pcc_begin_return + .return n + .pcc_end_return +.end + +.sub fibA method + .param int n + if n >= 2 goto rec + .pcc_begin_return + .return n + .pcc_end_return +rec: + .sym int n1 + .sym int n2 + .sym int r1 + .sym int r2 + n1 = n - 1 + n2 = n - 2 + r1 = self.fib(n1) + r2 = self.fibB(n2) + n = r1 + r2 + .pcc_begin_return + .return n + .pcc_end_return +.end + +.namespace ["B"] + +.sub fibB method + .param int n + if n >= 2 goto rec + .pcc_begin_return + .return n + .pcc_end_return +rec: + .sym int n1 + .sym int n2 + .sym int r1 + .sym int r2 + n1 = n - 1 + n2 = n - 2 + r1 = self.fib(n1) + r2 = self.fibA(n2) + n = r1 + r2 + .pcc_begin_return + .return n + .pcc_end_return +.end --- nonexistent Tue Mar 16 22:18:01 2004 +++ ./examples/benchmarks/method1.py Tue Mar 16 18:46:00 2004 @@ -0,0 +1,27 @@ +#! python + +import sys + +class A: + def fib(self,n): + if (n < 2): + return(n) + return( self.fibA(n-2) + self.fibB(n-1) ) + def fibA(self,n): + if (n < 2): + return(n) + return( self.fib(n-2) + self.fibB(n-1) ) + + +class B (A): + def fibB(self,n): + if (n < 2): + return(n) + return( self.fib(n-2) + self.fibA(n-1) ) + + +N = int(len(sys.argv) == 2 and sys.argv[1] or 24) + +b = B() + +print "fib(%d) = %d" %( N, b.fib(N) )