2010-12-20

The Scheme of things/2

In one of my previous posts I compared Clojure with Python by implementing two identical versions of a program to solve problem 34 from Project Euler in both languages. My results showed that Clojure was able to be three times faster than Python when type hinting (TH) was enabled (even without TH Clojure was however faster than Python). My idea was then that any type-hinted (semi-)interpreted language like Clojure would have reached the same speed.

In the last month I have run some other tests, and I must say that my idea has changed. A number of Scheme/Common LISP implementation have proven to be even faster than Clojure, and this without type hints!

I am not going to provide my Common LISP and Scheme programs, as they are trivial conversions of the Clojure program I presented before. These are the compilers/interpreters I used to write and run my test programs:

NameVersionLanguageTiming
Ikarus0.4 RC1Scheme14
Larceny0.97Scheme15
Bigloo3.5aScheme16
Steel Bank CL1.0.44Common LISP17
MZScheme (DrRacket)5.0.1Scheme17
STklos1.0Scheme43
CMU CL20bCommon LISP47
Clozure CL1.5Common LISP62
Chicken4.6.3Scheme93
Chicken4.4.0Scheme102
CLISP2.49Common LISP106
CPython (fast)2.6.6Python135
CPython2.6.6Python145
ECL10.4.1Common LISP169

The "CPython (fast)" entry is a rewrite of my original Python program so that the body of solution does not call other Python functions:

sum ([num for num in xrange (10, max_n)
      if num == sum ([FAST_FACT[digit]
                      for digit in [int(x)
                                    for x in list (str (num))]])])

A few notes about these results:

  • There is more than one order of magnitude between the slowest implementation (ECL) and the fastest (Ikarus Scheme);
  • Compilers without TH (e.g. Ikarus, Larceny, Bigloo, SBCL) run much faster than Clojure with TH. I was really surprised!
  • Avoiding function calls make CPython faster, but not much faster;
  • The fastest program runs using Ikarus, a compiler in alpha stage that has been put on hiatus after the author (apparently) changed his job. What a pity! (Note however that Marco Maggi has forked Ikarus into Vicare, which seems to be actively developed.)
  • While I had to change my Scheme program in order to make it runnable under various Scheme compilers/interpreters (nothing sensational, just one or two lines at the beginning), my Common LISP program ran unchanged under SBCL, ECL and CCL. One point for portability to Common LISP!

Here is a barchart of the results (click to zoom):

Update: After a suggestion by Water I included in my benchmarks also CLISP (and corrected the name) and CMU Lisp (which was mentioned in one of the pages at CLISP's site as being faster than CLISP – and indeed it is). In both cases I first compiled the program and then timed the execution of the bytecode. I have also added MZScheme, which I left out in the first version of this post. The table and the chart have been updated accordingly.