115 lines
3.0 KiB
Python
115 lines
3.0 KiB
Python
|
|
|
|
from __future__ import division, unicode_literals, print_function, absolute_import
|
|
|
|
import fnmatch
|
|
import os
|
|
import copy
|
|
from timeit import Timer
|
|
|
|
import yaml
|
|
|
|
|
|
def time_stmt(stmt='pass', setup='pass', number=0, repeat=3):
|
|
"""Timer function with the same behaviour as running `python -m timeit `
|
|
in the command line.
|
|
|
|
:return: elapsed time in seconds or NaN if the command failed.
|
|
:rtype: float
|
|
"""
|
|
|
|
t = Timer(stmt, setup)
|
|
|
|
if not number:
|
|
# determine number so that 0.2 <= total time < 2.0
|
|
for i in range(1, 10):
|
|
number = 10**i
|
|
|
|
try:
|
|
x = t.timeit(number)
|
|
except:
|
|
print(t.print_exc())
|
|
return float('NaN')
|
|
|
|
if x >= 0.2:
|
|
break
|
|
|
|
try:
|
|
r = t.repeat(repeat, number)
|
|
except:
|
|
print(t.print_exc())
|
|
return float('NaN')
|
|
|
|
best = min(r)
|
|
|
|
return best / number
|
|
|
|
|
|
def build_task(task, name='', setup='', number=0, repeat=3):
|
|
nt = copy.copy(task)
|
|
|
|
nt['name'] = (name + ' ' + task.get('name', '')).strip()
|
|
nt['setup'] = (setup + '\n' + task.get('setup', '')).strip('\n')
|
|
nt['stmt'] = task.get('stmt', '')
|
|
nt['number'] = task.get('number', number)
|
|
nt['repeat'] = task.get('repeat', repeat)
|
|
|
|
return nt
|
|
|
|
|
|
def time_task(name, stmt='pass', setup='pass', number=0, repeat=3, stmts='', base=''):
|
|
|
|
if base:
|
|
nvalue = time_stmt(stmt=base, setup=setup, number=number, repeat=repeat)
|
|
yield name + ' (base)', nvalue
|
|
suffix = ' (normalized)'
|
|
else:
|
|
nvalue = 1.
|
|
suffix = ''
|
|
|
|
if stmt:
|
|
value = time_stmt(stmt=stmt, setup=setup, number=number, repeat=repeat)
|
|
yield name, value / nvalue
|
|
|
|
for task in stmts:
|
|
new_task = build_task(task, name, setup, number, repeat)
|
|
for task_name, value in time_task(**new_task):
|
|
yield task_name + suffix, value / nvalue
|
|
|
|
|
|
def time_file(filename, name='', setup='', number=0, repeat=3):
|
|
"""Open a yaml benchmark file an time each statement,
|
|
|
|
yields a tuple with filename, task name, time in seconds.
|
|
"""
|
|
with open(filename, 'r') as fp:
|
|
tasks = yaml.load(fp)
|
|
|
|
for task in tasks:
|
|
new_task = build_task(task, name, setup, number, repeat)
|
|
for task_name, value in time_task(**new_task):
|
|
yield task_name, value
|
|
|
|
|
|
def recursive_glob(rootdir='.', pattern='*'):
|
|
return [os.path.join(looproot, filename)
|
|
for looproot, _, filenames in os.walk(rootdir)
|
|
for filename in filenames
|
|
if fnmatch.fnmatch(filename, pattern)]
|
|
|
|
def main(filenames=None):
|
|
if not filenames:
|
|
filenames = recursive_glob('.', 'bench_*.yaml')
|
|
elif isinstance(filenames, basestring):
|
|
filenames = [filenames, ]
|
|
|
|
for filename in filenames:
|
|
print(filename)
|
|
print('-' * len(filename))
|
|
print()
|
|
for task_name, value in time_file(filename):
|
|
print('%.2e %s' % (value, task_name))
|
|
print()
|
|
|
|
main()
|