Speed: bytecode vz C API calls

Jacek Generowicz jacek.generowicz at cern.ch
Fri Dec 12 05:17:16 EST 2003


bokr at oz.net (Bengt Richter) writes:

> On Tue, 9 Dec 2003 23:50:06 -0500, "Francis Avila" <francisgavila at yahoo.com> wrote:
> 
> >Stuart Bishop wrote in message ...
> >>About the only thing that could be done then is:
> >>
> >>def memoize(callable):
> >>    cache = {}
> >>    def proxy(*args, _cache=cache):

To be honest, I have trouble believing that a local variable lookup
would be significantly faster than a closure lookup ... or is there
some other point to this ?

> >Not legal.  *args must always come after default args. There's no way to do
> Never say never ;-)
> A function has the __get__ method, which is what getattr magic uses
> to make a bound method.  You can use this put cache in the "self"
> position of a bound method, like
> 
>  >>> def sq(x): return x*x
>  ...
>  >>> def memoize(func): # callable is a builtin ;-)
>  ...     def proxy(cache, *args):
>  ...         try: return cache[args]
>  ...         except KeyError: return cache.setdefault(args, func(*args))
>  ...     return proxy.__get__({}, proxy.__class__)


> Looking at the code, it might be worth timing, if you have 90%+ cache hits.
> I'd be curious to see what you get

I get your version being almost imperceptibly slower.

I used this:

import timing
import sys

def Amemoize(func):
     def proxy(cache, *args):
         try: return cache[args]
         except KeyError: return cache.setdefault(args, func(*args))
     return proxy.__get__({}, proxy.__class__)


def Bmemoize(func):
    cache = {}
    def proxy(*args):
        try: return cache[args]
        except KeyError: return cache.setdefault(args, func(*args))
    return proxy


N = int(sys.argv[1])

def foo(n):
    if n<2: return 1
    return foo(n-1) + foo(n-2)

Afoo = Amemoize(foo)
Bfoo = Bmemoize(foo)


Acode = """
def Acall():
    """ + "Afoo(10);" * N + "\n"

Bcode = """
def Bcall():
    """ + "Bfoo(10);" * N + "\n"

exec Acode
exec Bcode

timing.start()
Acall()
timing.finish()
print timing.micro()

timing.start()
Bcall()
timing.finish()
print timing.micro()




More information about the Python-list mailing list