While converting some of my Python 2 scripts to Python 3 I discovered notable performance differences. So I became interested in benchmarking Python 2 and 3. I also use Nuitka ( http://nuitka.net/
) to compile some of my Python stuff to binaries for different reasons (speed may be one of them).
Here are the results of the Pystone benchmarks for Python 2.7 and 3.4 and for compiled programs of both verions. Except for the time measurement the Pystone benchmark only uses functions built into the main Python library.
Python 2.7: 24344.88 pystones/second
Python 3.4: 17459.89 pystones/second
Nuitka 2.7: 47243.92 pystones/second
Nuitka 3.4: 28658.92 pystones/second
Python 2.7 / Python 3.4: 139.43 %
Nuitka 2.7 / Python 2.7: 194.06 %
Nuitka 3.4 / Python 3.4: 164.14 %
Nuitka 2.7 / Nuitka 3.4: 164.85 %
Nuitka 2.7 / Python 3.4: 270.59 %
Obviously Python 2.7 runs almost 40% faster than Python 3.4 code. The speed gain when compiling it with Nuitka is also greater for 2.7: 94% instead of 64%. And a compiled Python 2.7 program runs 2.7 times faster than an interpreted Python 3.4 script.
Does than mean, that you should use Python 2.7 instead of 3.4? For beginners and new (long time) projects I would not recommend it. For many projects, speed is not an issue at all. Inside a GUI for example, most of the time is spent waiting for user input or user events. And often it is better to look for Python wrappers of compiled C libraries for time critical stuff.
But if your project contains time critical Python routines, you might consider writing code that will run on both Python 2.7 and Python 3.4. That's not an easy task, but there are a number of tools available which help a lot. The best I found is the "future" package from http://python-future.org
(can be installed using pip and pip3). This website also provides a great "Cheat Sheet" which shows how to write code that will run on both Python versions (also available as PDF document http://python-future.org/compatible_idioms.pdf
). The "future" package also contains two great utilities: "futurize" ( to help converting 2.7 to 3.4) and "pasteurize" (to help creating 2.7 compatible code from 3.4 sources).
There's one drawback, though: if you want to distribute your code, you must make sure, that the "future" package is installed. Unfortunately it is not available as a Debian (Raspbian) package and so it's not possible to add it as a dependency to a Debian package.
Other tools: Cython and PyPy.
I've also compiled pystone with Cython (2.7 only), but got only about 10% speed gain. So it's not really worth the effort. Adding Cython specific code might help, but I didn't try that.
Often PyPy is recommended to speed up Python code using a JIT compiler. The Pystone benchmark gives different results, depending on the number of loops:
1000 loops: 5770.32 pystones/second (slower than 2.7 interpreter)
5000 loops: 27645.2 pystones/second (slightly faster than 2.7 interpreter)
10000 loops: 52145.1 pystones/second (faster than 2.7 compiled with Nuitka)
100000 loops: 248133 pystones/second (really much faster!).
Currently PyPy is only available on the RPi for Python 2.7. Using it in real world applications may lead to difficulties because of its memory usage. For my DVB application I needed a script to extract EPG information in real time from a DVB stream (up to 10 MBit/sec). I found a script from another project, which worked quite well, but needed some speed improvement. I ended up in running it as a separate application (compiled with Nuitka as 2.7 code), to make sure it will run on a separate core. I also tested using it with PyPy. It seemed to work fine, but my system almost froze after a short while (starting to swap). Watching the memory I discovered that it used up to 480 MB, while the compiled Nuitka script never used more than about 70 MB. Fast, yes, but not usable.