Re: OCaml vs. SBCL, and various other interpreters

"A. Pagaltzis" <[email protected]>
Newsgroups gmane.culture.people.kragen.discuss
Message-ID <20070312134858.GC4792@klangraum>
* Kragen Javier Sitaker <[email protected]> [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/>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.