Slow recursive functions

Andrew Haley aph@redhat.com
Fri Apr 15 10:44:00 GMT 2005


Christian Mayrhuber writes:
 > Hi,
 > 
 > I compiled the ackermann source from the computer language shootout with
 > j2se 1.5 and gcj and ran a simple benchmark:
 > 
 > ackermann$ time java -server ackermann 12
 > Ack(3,12): 32765
 > 
 > real    0m4.312s
 > user    0m4.104s
 > sys     0m0.029s
 > 
 > ackermann$ time ./ackermann.java.elf 12
 > Ack(3,12): 32765
 > 
 > real    0m32.301s
 > user    0m30.667s
 > sys     0m0.039s
 > 
 > This result surprised me. The native compiled program was 8x slower than
 > the version run by the sun jvm.
 > 
 > I've included the java source file and the -Os optimized
 > assembler output.
 > 
 > My suspect are the calls of _Jv_InitClass in
 > _ZN9ackermann3AckEii function.

That, and the calling convention.  We use the x86 system calling
convention throughout gcj, and this is slower than passing args in
registers.  There's also the possibility that some JITs might be
optimized for this kind of benchmark.

Make Ack private and the _Jv_InitClass calls should go away.
 
With -O2 -fomit-frame-pointer and ackermann.Ack declared private I get
this:

ackermann.Ack(int, int):
.LFB3:
        pushl   %ebx
.LCFI0:
        subl    $8, %esp
.LCFI1:
        movl    16(%esp), %edx
        movl    20(%esp), %eax
        testl   %edx, %edx
        jne     .L10
.L3:
        addl    $8, %esp
        incl    %eax
        popl    %ebx
        ret
        .p2align 4,,7
.L12:
        leal    -1(%edx), %ebx
        movl    $1, %eax
.L5:
        testl   %ebx, %ebx
        je      .L3
        movl    %ebx, %edx
.L10:
        testl   %eax, %eax
        je      .L12
        decl    %eax
        leal    -1(%edx), %ebx
        movl    %eax, 4(%esp)
        movl    %edx, (%esp)
        call    ackermann.Ack(int, int)
        jmp     .L5

I can't duplicate your jit results because I get a stack overflow.

Andrew.



More information about the Java mailing list