"""
timethis.py
Author : David Beazley
http://www.dabeaz.com
Copyright (C) 2010
timethis is a utility library for making simple timing benchmarks. A
single function timethis() is provided. The function operates as
either a context manager or a decorator. Here are some examples.
If you want to time a block of code, do this:
with timethis("Counting to a million"):
n = 0
while n < 1000000:
n += 1
The string in quotes is a description that describes the code block
in question. It will be printed in the output.
If you want to time a function, you can use a decorator:
@timethis
def count_to_a_million():
n = 0
while n < 1000000:
n += 1
count_to_a_million()
All timing output is collected and not printed until a program
exits. If any code block or function marked with timethis() is
executed more than once, timing measurements are collected
and used to calculate a mean and standard deviation.
"""
import atexit
import time
import math
from contextlib import contextmanager
from collections import defaultdict
# Dictionary holding timing measurements
_stats = defaultdict(list)
# Exit processing to print performance results
def _printstats():
if not _stats:
return
maxwidth = max(len(str(key)) for key in _stats)
for key,times in sorted(_stats.items(),key=lambda x: str(x[0])):
# Compute average and standard deviation
mean = sum(times)/float(len(times))
stddev = math.sqrt(sum((x-mean)**2 for x in times)/len(times))
print("{0:<{maxwidth}s} : {1:0.5f}s : N={2:5d} : stddev={3:0.5f}".format(
key,mean,len(times),stddev,maxwidth=maxwidth))
atexit.register(_printstats)
# This utility function is used to perform timing benchmarks
def timethis(what):
@contextmanager
def benchmark():
start = time.time()
yield
end = time.time()
_stats[what].append(end-start)
if hasattr(what,"__call__"):
def timed(*args,**kwargs):
with benchmark():
return what(*args,**kwargs)
return timed
else:
return benchmark()
# Example
if __name__ == '__main__':
# A single measurement
with timethis("count to ten million"):
n = 0
while n < 10000000:
n += 1
# Repeated measurements
for i in range(10):
with timethis("count to one million"):
n = 0
while n < 1000000:
n += 1
# A function call
@timethis
def count_to_a_million():
n = 0
while n < 1000000:
n += 1
count_to_a_million()
count_to_a_million()
count_to_a_million()