Ilan Schnell, 2008-06-17
The PyPy project has some very nice things in it. Among those things is the translator module. The purpose of this module is to compile a restricted subset of Python (RPython) into C and other lower level languages. Within the PyPy project, the translator is used to compile the PyPy interpreter. However, it is also possible to compile individual Python functions at runtime and dynamically execute the compiled function. The translator module makes this task very easy. I have written a class which allows using the compiled version of a Python functions simply by adding a decorator to the function. The nice thing about doing things this way is that all the code is pure Python code, and switching between the compiled and uncompiled version of the function is as simple as possible.
# compdec.py
import sys
sys.path.append('<path-to>.../pypy-dist')
from pypy.translator.interactive import Translation
class compdec:
def __init__(self, func):
self.func = func
self.argtypes = None
def __call__(self, *args):
argtypes = tuple(type(arg) for arg in args)
if argtypes != self.argtypes:
self.argtypes = argtypes
t = Translation(self.func)
t.annotate(argtypes)
self.cfunc = t.compile_c()
return self.cfunc(*args)
Using the compile decorator:
from compdec import compdec
@compdec
def is_prime(n):
if n < 2:
return False
for i in xrange(2, n):
if n%i == 0:
return False
return True
print sum(is_prime(n) for n in xrange(100000))
Execution times (on 2.4GHz machine):
Compilation takes about 2 seconds
Python loop using compiled function runs in 4 seconds
Pure Python program runs in 70 seconds
References: