Mandelbrot Set Example

This code does a very straightforward calculation of the Mandelbrot set. There's nothing special about this test, other than the fact that it's calculation-heavy, so makes a nice semi-realistic speed test. Of course, as with all benchmarks, this should be taken for what it is: a single algorithm on a single test machine, tested with some care, but not perfectly. Fundamentally, it is a flawed benchmark, like every other benchmark.

Everything was run with the reference Python implementation (CPython) 2.7.3 on 64-bit Linux unless otherwise noted. In the code, I have ignored the built-in complex numbers type: I wanted to test straightforward numerical calculations, not the possibly-less-optimized complex type.

Here are the files used in the example:

Cython Version

The “static” implementation is based on Cython (cython in Ubuntu). It is a very-Python-like language that adds optional static typing. This version, static.pyx, is the same as dynamic.py with static type declarations added to the arguments and variables in the escapes function.

With the setup.py file, this module can be built with the command:

python setup.py build_ext --inplace

Since Cython can also compile (most) Python code, I also ran the original dynamic.py version after compiling with Cython.

Other Runs

Having a somewhat arbitrary but functional benchmark sitting around, I was curious about other Python implementations, so I tested those as well.

Python 3 is the next version of Python. It contains some backwards-incompatible changes, so adoption has been slow. (In this case, only the xrange function had to be changed to range).

Jython compiles Python to the JVM (and allows integration with Java classes).

IronPython compiles Python to the .NET CLR. For IronPython, the comparison was made on a Windows 7 machine running Python for Windows.

PyPy is a reimplementation of the Python compiler/interpreter in Python itself. It includes a JIT compiler among other tricks.

Other Languages

And since I had done all of that, who could resist a inter-language shootout? I duplicated the calculations from the Python program as closely as I could (including continuing to ignore any complex number types).

I reimplemented the program in Haskell, C, Java, Javascript, and Ruby, with code and versions as below.

Results

(You can click on column headings in the table to sort.)

Speedup of Mandelbrot calculation (multiples of original Python implementation)
LanguageImplementationCodeSpeedup
PythonPython 2.7.3dynamic.py1.0
PythonPython 2.7.3 with -Odynamic.py1.0
PythonCython 0.15.1dynamic.py1.8
CythonCython 0.15.1static.pyx109.5
PythonPython 3.2.3dynamic.py1.0
PythonJython 2.2.1dynamic.py3.6
PythonIronPythondynamic.py1.9
PythonPyPy 1.8dynamic.py94.3
PythonPyPy 1.9dynamic.py93.5
HaskellGHC 7.4.1mandel.hs1.9
HaskellGHC 7.4.1 with -O2mandel.hs60.3
CGCC 4.6.3mandel.c55.4
CGCC 4.6.3 with -O2mandel.c109.9
CClang 3.0mandel.c51.2
CClang 3.0 with -O2mandel.c102.8
JavaOpenJDK 6b24Mandel.java107.5
JavaGCJ 4.6.3Mandel.java41.5
JavaGCJ 4.6.3 with -O2Mandel.java109.5
JavascriptFirefox 13.0mandel.html56.7
JavascriptChromium 18.0mandel.html95.9
RubyRuby 1.8.7mandel.rb0.3
RubyRubinus 1.2.4mandel.rb1.0

Weird Stuff

Since I have all the code around, I seem to have the compulsion to keep trying it with other tools. None of these are serious “benchmarks”, but they're interesting anyway.

LanguageImplementationCodeSpeedup
PythonPython 2.7.3dynamic.py1.0
PythonPyPy's rpython translatorrpython.py105.4
CPicoC 2.1 (compiled with -O2)mandel.c0.13
HaskellHugs Sept 2006mandel.hs0.04

Copyright © , last modified 2012-06-25.