OCaml vs. SBCL, and various other interpreters

A. Pagaltzis pagaltzis at gmx.de
Mon Mar 12 09:48:58 EDT 2007


* Kragen Javier Sitaker <kragen at pobox.com> [2007-03-12 08:40]:
> The Microbenchmark (OCaml, Python, Perl, Ruby, Elisp, Tcl)

I thought it would be interesting to know how Parrot fares as a
target.

What I gather is that targetting Parrot is quite nice, with a
bunch of tools to make compiler-writing nice that aren’t exactly
finished, but are shaping up. F.ex you can write the parser in
a large subset of Perl 6 grammars, though it is not finished and
as yet only implements a subset of the subset.

> There's a microbenchmark I like to run on language
> implementations; here's the OCaml version:
> 
>     let rec fib n = if n < 2 then 1 else fib (n-1) + fib (n-2) in
>     print_int (fib 32) ; print_newline() ;;

This is a version written in PIR (Parrot Intermediate
Representation):

    .sub fib
        .param int n
        if n < 2 goto BASE
        .local int f2
        .local int ret
        n -= 1
        ret = fib(n)
        n -= 1
        f2 = fib(n)
        ret += f2
        .return(ret)
    BASE:
        .return(1)
    .end

    .sub main :main
        .local int result
        result = fib(32)
        print result
        print "\n"
    .end

There may be better ways to write this; it’s the first time I
wrote anything in PIR at all.

Unfortunately, I find it runs significantly slower than the Perl
version regardless of which Parrot “runcore” I use and whether or
not I enable optimisations. The CGP core is the fastest (faster
than the JIT core) at ~8.6s user time on my system whereas the
Perl version runs in ~6.3s (per bash’s `time` builtin).

For completeness, here is the disassembled code of the fib
function:

    get_params_pc PMC_CONST(3)
    lt_i_ic_ic I2,2,L1
    sub_i_ic I2,1
    set_args_pc PMC_CONST(3)
    set_p_pc P0,PMC_CONST(6)
    get_results_pc PMC_CONST(3)
    invokecc_p P0
    sub_i_ic I2,1
    set_args_pc PMC_CONST(3)
    set_p_pc P1,PMC_CONST(6)
    get_results_pc PMC_CONST(3)
    invokecc_p P1
    add_i_i I0,I1
    set_returns_pc PMC_CONST(3)
    returncc 
    L1: set_returns_pc PMC_CONST(1)
    returncc 

Of course, since the code was PIR to begin with, the difference
is not that interesting – it’s the same thing, except with the
convenient PIR shortcuts expanded to bare-metal PASM.

The resulting bytecode file is 1088 bytes in size, but looking at
it with a hex viewer, I see there’s a lot of extra file format
glop in there. So I have no idea how much space the actual
bytecode is taking up. However, a file that also contains the
`main` function comes out at 1504 bytes. Even if the presence of
an extra function adds a lot more file format glop, it seems
evident that Parrot bytecode is pretty bulky.

Of course, Parrot is far from finished and the stated performance
goal for Perl 6 is to be at least twice as fast as Perl 5, which
means Parrot is supposed to get a lot faster yet. In particular
I’m pretty sure that little work has gone into the JIT runcore.

I’m not sure what to take away from this.

Regards,
-- 
Aristotle Pagaltzis // <http://plasmasturm.org/>


More information about the Kragen-discuss mailing list