Created
July 8, 2011 11:30
-
-
Save aliles/1071645 to your computer and use it in GitHub Desktop.
Benchmark repeated calls to a tail call optimisation decorator.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[aliles@macbookpro ~]$ time python2.7 timeit_tco.py 100 60000 | |
Maximum time on CPU: 0.00030600 | |
Minimum time on CPU: 0.00014800 | |
Average time on CPU: 0.00015401 | |
real 0m9.586s | |
user 0m9.473s | |
sys 0m0.110s | |
[aliles@macbookpro ~]$ time pypy timeit_tco.py 100 60000 | |
Maximum time on CPU: 0.00829600 | |
Minimum time on CPU: 0.00003300 | |
Average time on CPU: 0.00006019 | |
real 0m4.557s | |
user 0m4.427s | |
sys 0m0.128s | |
[aliles@macbookpro ~]$ time python2.7 timeit_tco.py 1000 6000 | |
Maximum time on CPU: 0.00230600 | |
Minimum time on CPU: 0.00196600 | |
Average time on CPU: 0.00200732 | |
real 0m13.698s | |
user 0m13.654s | |
sys 0m0.033s | |
[aliles@macbookpro ~]$ time pypy timeit_tco.py 1000 6000 | |
Maximum time on CPU: 0.01351100 | |
Minimum time on CPU: 0.00179300 | |
Average time on CPU: 0.00186320 | |
real 0m19.049s | |
user 0m18.949s | |
sys 0m0.090s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import namedtuple | |
import sys | |
import time | |
Stats = namedtuple('Stats', 'maximum minimum average digits') | |
class tail_recursive(object): | |
"""Tail recursion decorator by George Sakkis | |
http://code.activestate.com/recipes/496691-new-tail-recursion-decorator/#c3 | |
""" | |
def __init__(self, func): | |
self.func = func | |
self.firstcall = True | |
self.CONTINUE = object() | |
def __call__(self, *args, **kwd): | |
if self.firstcall: | |
func = self.func | |
CONTINUE = self.CONTINUE | |
self.firstcall = False | |
try: | |
while True: | |
result = func(*args, **kwd) | |
if result is CONTINUE: # update arguments | |
args, kwd = self.argskwd | |
else: # last call | |
return result | |
finally: | |
self.firstcall = True | |
else: # return the arguments of the tail call | |
self.argskwd = args, kwd | |
return self.CONTINUE | |
@tail_recursive | |
def factorial(n, acc=1): | |
"calculate a factorial" | |
if n == 0: | |
return acc | |
res = factorial(n-1, n*acc) | |
return res | |
def factorial_loop(depth, loops=1, step=0): | |
maximum = None | |
minimum = Ellipsis | |
total = 0.0 | |
digits = 0 | |
for loop in xrange(loops): | |
start = time.clock() | |
value = factorial(depth) | |
stop = time.clock() | |
cost = stop - start | |
maximum = max(maximum, cost) | |
minimum = min(minimum, cost) | |
total += cost | |
digits += len(str(value)) | |
depth += step | |
average = total / loops | |
return Stats(maximum, minimum, average, digits) | |
if __name__ == '__main__': | |
depth = int(sys.argv[1]) | |
loops = int(sys.argv[2]) | |
stats = factorial_loop(depth, loops, 0)._asdict() | |
print "Maximum time on CPU: %(maximum).8f" % stats | |
print "Minimum time on CPU: %(minimum).8f" % stats | |
print "Average time on CPU: %(average).8f" % stats |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment