"""
standard python2.7.3 (0 downsizings):
    Mean time per run: 0.211269285679

with downsizing (with fill > 2*used... 14059 downsizings in total):
    Mean time per run: 0.20978112936
"""

from collections import OrderedDict
import random

class LimitCache(OrderedDict):
    def __setitem__(self, key, value):
        if len(self) >= 50:
            super(OrderedDict, self).popitem()
        super(OrderedDict, self).__setitem__(key, value)

def memoize(fxn):
    cache = LimitCache()
    def new_fxn(*args):
        if args in cache:
            return cache[args]
        value = fxn(*args)
        cache[args] = value
        return value
    return new_fxn

@memoize
def foo(bar):
    return 2*bar

def benchmark():
    for i in xrange(50000):
        foo(random.randint(0,100))

if __name__ == "__main__":
    import timeit
    result = timeit.repeat(
        "benchmark()", 
        setup = "from __main__ import benchmark; gc.enable()", 
        number = 1,
        repeat = 100,
    )
    print "Mean time per run:", sum(result) / float(len(result))
