Enthought / ~ischnell

Compile decorator

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):

References: