In a previous post, I mentioned that PyPy was the fastest Python implementation for most of my Project Euler programs, but that it was very slow for a few of them.
This is no longer the case. The jit-generator branch was merged a few days ago, fixing a weakness with code that uses generators. And now PyPy is clearly the fastest Python implementation for this code, with both the most wins and the lowest overall time. Psyco is still pretty close. Both are a bit more than twice as fast as CPython.
I compared PyPy trunk, Unladen Swallow trunk, Jython 2.5.1+, CPython 2.6.6 with Psyco, and CPython 2.7.
PyPy is very strong across the board. Its worst result is on euler94, a Sudoku solver that heavily uses sets and copy.deepcopy.
Psyco still does very well, but it doesn't work on Python 2.7 yet and still doesn't work on amd64, so it feels more and more like a dead end.
Unladen Swallow hasn't had a commit since August. I suspect it's just resting, not dead, but it's falling behind PyPy in performance. Version 2.8 of LLVM has been released, but Unladen still requires version 2.7.
CPython is the baseline. I used 2.7, the latest Python 2. (Some of my Euler programs work in Python 3; some don't.)
Jython is by far the slowest. Its large startup overhead hurts on the easy problems, and the mature HotSpot JIT isn't enough for it to catch up on the harder ones. Jython does have the advantage of being free-threaded, but since this code was originally written for CPython it rarely uses multiple threads and so doesn't really benefit.
Here are the numbers.
script | PyPy | Unladen | Jython | Psyco | CPython |
---|---|---|---|---|---|
euler1.py | 0.01 | 0.12 | 3.65 | 0.10 | 0.02 |
euler2.py | 0.10 | 0.10 | 3.94 | 0.10 | 0.10 |
euler3.py | 0.23 | 0.91 | 6.40 | 0.51 | 0.40 |
euler4.py | 0.31 | 0.84 | 6.49 | 0.41 | 0.42 |
euler5.py | 0.12 | 0.12 | 5.38 | 0.12 | 0.12 |
euler6.py | 0.12 | 0.11 | 5.50 | 0.12 | 0.11 |
euler7.py | 0.33 | 0.52 | 7.29 | 0.12 | 0.73 |
euler8.py | 0.13 | 0.12 | 4.77 | 0.11 | 0.11 |
euler9.py | 0.11 | 0.32 | 6.67 | 0.10 | 0.21 |
euler10.py | 2.34 | 6.02 | 11.81 | 1.93 | 12.02 |
euler11.py | 0.10 | 0.10 | 4.28 | 0.10 | 0.11 |
euler13.py | 0.10 | 0.10 | 3.36 | 0.10 | 0.10 |
euler14.py | 3.88 | 2.76 | 8.46 | 1.96 | 3.07 |
euler15.py | 0.11 | 0.11 | 4.00 | 0.10 | 0.10 |
euler16.py | 0.11 | 0.12 | 3.58 | 0.11 | 0.13 |
euler18.py | 0.10 | 0.10 | 3.45 | 0.10 | 0.10 |
euler19.py | 0.13 | 0.11 | 3.06 | 0.12 | 0.10 |
euler20.py | 0.10 | 0.10 | 2.45 | 0.10 | 0.10 |
euler21.py | 0.10 | 0.21 | 4.16 | 0.10 | 0.21 |
euler22.py | 0.10 | 0.10 | 3.95 | 0.10 | 0.10 |
euler23.py | 3.84 | 21.33 | 15.36 | 4.45 | 12.03 |
euler24.py | 5.97 | 5.66 | 31.25 | 6.97 | 5.46 |
euler25.py | 0.71 | 0.91 | 3.44 | 0.91 | 0.20 |
euler26.py | 9.59 | 10.84 | 20.61 | 9.74 | 3.54 |
euler27.py | 1.33 | 7.08 | 12.35 | 1.32 | 11.33 |
euler28.py | 0.11 | 0.12 | 4.37 | 0.12 | 0.11 |
euler29.py | 0.22 | 0.12 | 6.49 | 0.12 | 0.22 |
euler30.py | 3.95 | 4.45 | 10.72 | 5.37 | 4.26 |
euler32.py | 2.83 | 3.54 | 9.20 | 4.95 | 3.34 |
euler33.py | 0.11 | 0.12 | 5.26 | 0.11 | 0.10 |
euler34.py | 4.35 | 12.33 | 13.86 | 12.67 | 16.08 |
euler35.py | 5.59 | 18.19 | 30.04 | 6.47 | 25.47 |
euler36.py | 1.83 | 3.24 | 7.39 | 2.93 | 2.44 |
euler37.py | 10.92 | 12.44 | 39.17 | 14.57 | 17.50 |
euler38.py | 2.24 | 1.31 | 9.91 | 2.14 | 2.34 |
euler39.py | 0.21 | 0.42 | 5.79 | 0.10 | 0.41 |
euler40.py | 1.12 | 1.63 | 7.30 | 0.42 | 1.13 |
euler41.py | 4.25 | 3.94 | 20.63 | 5.46 | 4.76 |
euler42.py | 0.11 | 0.21 | 4.98 | 0.12 | 0.11 |
euler44.py | 0.91 | 9.41 | 7.48 | 1.02 | 3.75 |
euler45.py | 8.01 | 2.73 | 12.06 | 2.73 | 2.12 |
euler46.py | 0.52 | 1.13 | 6.98 | 0.31 | 1.14 |
euler47.py | 1.44 | 2.44 | 8.03 | 0.73 | 3.65 |
euler48.py | 0.10 | 0.20 | 5.49 | 0.21 | 0.10 |
euler49.py | 0.62 | 1.74 | 6.72 | 0.82 | 1.02 |
euler50.py | 2.23 | 52.50 | 58.27 | 6.11 | 56.61 |
euler52.py | 0.61 | 0.81 | 5.36 | 0.82 | 0.71 |
euler53.py | 0.22 | 0.42 | 5.98 | 0.21 | 0.42 |
euler54.py | 0.41 | 0.32 | 7.59 | 0.32 | 0.32 |
euler55.py | 0.82 | 0.73 | 6.39 | 0.52 | 0.73 |
euler56.py | 0.92 | 1.22 | 5.98 | 1.03 | 1.43 |
euler57.py | 0.52 | 0.72 | 6.09 | 0.53 | 0.82 |
euler58.py | 6.67 | 34.19 | 44.30 | 7.60 | 53.89 |
euler59.py | 11.42 | 8.19 | 17.06 | 12.81 | 14.35 |
euler61.py | 0.31 | 0.21 | 5.38 | 0.11 | 0.10 |
euler62.py | 0.42 | 0.32 | 6.49 | 0.53 | 0.22 |
euler63.py | 0.21 | 0.21 | 6.89 | 0.20 | 0.11 |
euler65.py | 0.10 | 0.10 | 3.85 | 0.10 | 0.10 |
euler66.py | 1.92 | 7.68 | 23.86 | 7.18 | 12.33 |
euler67.py | 0.11 | 0.12 | 4.77 | 0.11 | 0.12 |
euler68.py | 0.11 | 0.12 | 4.16 | 0.10 | 0.11 |
euler69.py | 0.11 | 0.21 | 4.96 | 0.11 | 0.11 |
euler70.py | 0.73 | 0.61 | 7.18 | 1.02 | 1.22 |
euler71.py | 0.21 | 1.44 | 6.48 | 0.32 | 0.91 |
euler72.py | 7.23 | 30.18 | 37.07 | 8.42 | 49.23 |
euler73.py | 9.50 | 22.54 | 21.23 | 3.35 | 24.59 |
euler75.py | 2.12 | 2.22 | 5.56 | 0.62 | 2.43 |
euler77.py | 0.41 | 0.30 | 4.86 | 0.20 | 0.41 |
euler79.py | 0.10 | 0.10 | 3.13 | 0.10 | 0.10 |
euler80.py | 0.91 | 0.71 | 3.94 | 0.72 | 0.62 |
euler81.py | 0.10 | 0.20 | 3.54 | 0.10 | 0.10 |
euler82.py | 0.71 | 0.30 | 8.70 | 0.30 | 0.20 |
euler83.py | 0.20 | 0.81 | 4.04 | 0.41 | 0.61 |
euler84.py | 2.65 | 15.13 | 23.56 | 4.66 | 19.91 |
euler85.py | 7.98 | 7.99 | 22.23 | 10.41 | 13.85 |
euler87.py | 1.93 | 1.74 | 7.28 | 1.03 | 1.23 |
euler89.py | 0.11 | 0.11 | 5.17 | 0.11 | 0.10 |
euler93.py | 3.54 | 5.56 | 12.72 | 6.58 | 12.33 |
euler94.py | 34.69 | 29.33 | 24.57 | 26.20 | 20.42 |
euler97.py | 3.64 | 4.95 | 10.61 | 2.63 | 3.13 |
euler98.py | 0.41 | 0.61 | 3.84 | 0.51 | 0.61 |
euler99.py | 0.10 | 0.10 | 2.12 | 0.10 | 0.10 |
euler100.py | 0.10 | 0.10 | 2.43 | 0.10 | 0.10 |
euler101.py | 0.20 | 0.10 | 4.76 | 0.10 | 0.10 |
euler102.py | 0.10 | 0.10 | 3.44 | 0.10 | 0.10 |
euler103.py | 0.10 | 0.12 | 2.94 | 0.10 | 0.10 |
euler105.py | 0.61 | 0.41 | 7.90 | 0.42 | 0.41 |
euler106.py | 0.71 | 0.51 | 8.82 | 0.41 | 0.51 |
euler107.py | 0.31 | 0.62 | 7.19 | 0.31 | 0.31 |
euler108.py | 3.66 | 19.55 | 17.52 | 8.86 | 10.62 |
euler109.py | 0.41 | 1.23 | 11.61 | 0.62 | 2.36 |
euler111.py | 2.64 | 17.94 | 25.92 | 6.19 | 17.00 |
euler112.py | 4.57 | 12.55 | 12.85 | 12.45 | 14.97 |
euler114.py | 0.11 | 0.21 | 5.17 | 0.10 | 0.11 |
euler115.py | 0.31 | 0.42 | 5.58 | 0.21 | 0.41 |
euler116.py | 0.11 | 0.12 | 4.86 | 0.11 | 0.12 |
euler117.py | 0.11 | 0.12 | 4.76 | 0.12 | 0.11 |
euler119.py | 0.10 | 0.11 | 3.74 | 0.10 | 0.10 |
euler120.py | 0.11 | 0.11 | 3.56 | 0.12 | 0.11 |
euler121.py | 0.20 | 0.30 | 4.87 | 0.11 | 0.32 |
euler123.py | 5.59 | 5.42 | 24.12 | 7.08 | 7.48 |
euler124.py | 1.24 | 1.84 | 9.22 | 0.62 | 2.77 |
euler125.py | 1.32 | 1.52 | 6.28 | 1.22 | 1.11 |
euler126.py | 4.06 | 15.59 | 13.75 | 3.85 | 17.70 |
euler128.py | 9.50 | 21.56 | 26.49 | 12.63 | 14.76 |
euler135.py | 3.34 | 5.36 | 7.48 | 2.22 | 3.34 |
euler142.py | 0.20 | 0.71 | 5.57 | 0.22 | 0.51 |
euler143.py | 0.11 | 0.11 | 4.46 | 0.11 | 0.10 |
euler157.py | 0.12 | 0.12 | 3.97 | 0.11 | 0.12 |
euler162.py | 0.10 | 0.10 | 3.44 | 0.10 | 0.10 |
euler171.py | 0.10 | 0.10 | 3.74 | 0.11 | 0.11 |
euler173.py | 0.93 | 1.12 | 6.17 | 0.61 | 1.53 |
euler174.py | 4.45 | 4.16 | 8.08 | 3.74 | 3.23 |
euler181.py | 0.10 | 0.10 | 3.85 | 0.11 | 0.10 |
euler190.py | 0.10 | 0.10 | 2.43 | 0.10 | 0.10 |
euler193.py | 0.10 | 0.10 | 2.12 | 0.10 | 0.10 |
euler202.py | 0.10 | 0.10 | 2.74 | 0.10 | 0.10 |
euler205.py | 0.92 | 0.72 | 10.16 | 1.03 | 0.72 |
euler207.py | 0.21 | 0.83 | 6.29 | 0.32 | 1.43 |
euler222.py | 0.10 | 0.10 | 3.44 | 0.10 | 0.10 |
euler233.py | 0.10 | 0.10 | 3.35 | 0.10 | 0.10 |
euler234.py | 4.46 | 9.00 | 19.12 | 7.71 | 7.48 |
euler235.py | 0.20 | 0.20 | 5.47 | 0.32 | 0.22 |
euler240.py | 14.57 | 14.52 | 48.67 | 12.14 | 22.65 |
total | 250.37 | 509.72 | 1211.07 | 282.73 | 569.37 |
wins | 68 | 33 | 0 | 59 | 51 |
[BLOCKED BY STBV] from boyd import jeremy | 22-Oct-10 at 5:28 pm | Permalink
PyPy outperforming CPython and Psyco…
David Ripton ran a bunch of implementations against his collection of Euler Challenge solutions: And now PyPy is clearly the fastest Python implementation for this code, with both the most wins and the lowest overall time. Â Psyco is still pretty close…
Matt Croydon::Postneo » Blog Archive » PyPy is Fast (And So Can You) | 18-Mar-11 at 8:33 am | Permalink
[…] For the ones I looked at, PyPy had a 50-75% speed improvement over CPython. David Ripton posted a more complete set of Euler solution runtimes using PyPy, Unladen Swallow, Jython, Psyco, and CPython. Almost all of the time, PyPy is faster, […]