-
Notifications
You must be signed in to change notification settings - Fork 0
/
QuickTimeIt.py
87 lines (75 loc) · 3.49 KB
/
QuickTimeIt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import timeit
import logging
import datetime
def quick_timeit(runs=1000, repeat=5, timing='sec', logfile=False):
def arg_wrap(func):
def wrapper(*args, **kwargs):
# set-up and soft 'failsafe' abort -------------------------
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.DEBUG)
if logfile:
handler = logging.FileHandler(
f'{func.__name__}.QTimeIt.log', mode='a'
)
else:
handler = logging.StreamHandler()
logger.addHandler(handler)
op_error = []
if not isinstance(runs, int):
op_error.append(f'runs={runs!r}')
if not isinstance(repeat, int):
op_error.append(f'repeat={repeat!r}')
if timing not in ['sec', 'milli', 'nano']:
op_error.append(f'timing={timing!r}')
if not isinstance(logfile, bool):
op_error.append(f'file={logfile!r}')
if op_error: # if syntax error, return func and discontinue
logger.info(
f'\n- QuickTimeIt() - Invalid quick_timeit() kwarg(s)! '
f'\nfunc : <{func.__name__}> - timing Aborted!'
f'\n--- kwarg(s) Syntax Error: --'
+ ', --'.join(op_error)
)
logger.removeHandler(handler)
return func(*args, **kwargs)
# ----------------------------------------------------------
timing_dic = {
'sec': (1, 'seconds'),
'milli': (1000, 'milliseconds'),
'nano': (10**9, 'nanoseconds')
}
time_rep = timeit.repeat(
lambda: func(*args, **kwargs),
repeat=repeat, number=runs
)
logging_out = f'\n- QuickTimeIt(): '
if logfile:
logging_out += f'call logged at {datetime.datetime.now()}'
logging_out += '\n--------------------------------------------'\
f'\ntiming func : <{func.__name__}> | repeat = {repeat}'
all_args = ', '.join(
[repr(a) for a in args]
+ [f'{k}={repr(v)}' for k, v in kwargs.items()]
)
if len(all_args) > 120:
all_args = all_args[:120] + ' .... <truncated> ..'
logging_out += f'\n*args/**kwargs : ({all_args})'\
f'\nnumber of runs : {runs}'\
f'\nmeasure in : {timing_dic[timing][1]}'\
'\ncompleted in : \n'
logging_out += ''.join(f'\n{run:>9}: - {measure*timing_dic[timing][0]:.9f} '
for run, measure in enumerate(time_rep, 1))
if repeat > 1:
logging_out += f'\n\n fastest: - ' \
f'{min(time_rep)*timing_dic[timing][0]:.9f} {timing_dic[timing][1]}\n' \
f' average: - ' \
f'{(sum(time_rep) / len(time_rep))*timing_dic[timing][0]:.9f} ' \
f'{timing_dic[timing][1]}'
else:
logging_out += timing_dic[timing][1]
logging_out += '\n--------------------------------------------'
logger.info(logging_out)
logger.removeHandler(handler)
return func(*args, **kwargs)
return wrapper
return arg_wrap