12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- """Simple tools for timing functions' execution, when IPython is not available. """
- import timeit
- import math
- _scales = [1e0, 1e3, 1e6, 1e9]
- _units = ['s', 'ms', '\N{GREEK SMALL LETTER MU}s', 'ns']
- def timed(func, setup="pass", limit=None):
- """Adaptively measure execution time of a function. """
- timer = timeit.Timer(func, setup=setup)
- repeat, number = 3, 1
- for i in range(1, 10):
- if timer.timeit(number) >= 0.2:
- break
- elif limit is not None and number >= limit:
- break
- else:
- number *= 10
- time = min(timer.repeat(repeat, number)) / number
- if time > 0.0:
- order = min(-int(math.floor(math.log10(time)) // 3), 3)
- else:
- order = 3
- return (number, time, time*_scales[order], _units[order])
- # Code for doing inline timings of recursive algorithms.
- def __do_timings():
- import os
- res = os.getenv('SYMPY_TIMINGS', '')
- res = [x.strip() for x in res.split(',')]
- return set(res)
- _do_timings = __do_timings()
- _timestack = None
- def _print_timestack(stack, level=1):
- print('-'*level, '%.2f %s%s' % (stack[2], stack[0], stack[3]))
- for s in stack[1]:
- _print_timestack(s, level + 1)
- def timethis(name):
- def decorator(func):
- global _do_timings
- if name not in _do_timings:
- return func
- def wrapper(*args, **kwargs):
- from time import time
- global _timestack
- oldtimestack = _timestack
- _timestack = [func.func_name, [], 0, args]
- t1 = time()
- r = func(*args, **kwargs)
- t2 = time()
- _timestack[2] = t2 - t1
- if oldtimestack is not None:
- oldtimestack[1].append(_timestack)
- _timestack = oldtimestack
- else:
- _print_timestack(_timestack)
- _timestack = None
- return r
- return wrapper
- return decorator
|