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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
#!/usr/bin/env python
"""
debug timer: measure run times of code, display results
"""
from time import time, perf_counter
from datetime import datetime
def isotime(dtime=None, sep=' '):
"return datetime isoformat"
if dtime is None:
dtime = datetime.now()
return datetime.isoformat(dtime, sep=sep)
def sleep(duration):
"more accurate sleep()"
end = perf_counter() + duration
while perf_counter() < end:
pass
class DebugTimer():
'''
Measure run times for lines of code and summarize results
'''
def __init__(self, title=None, verbose=False, precision=4):
self.verbose = verbose
if title is None:
title = "DebugTimer"
self.title = title
self.precision = precision
self.clear(title=title)
def clear(self, title=None):
"""clear debugtimer"""
self.data = []
if title is None:
title = self.title
self.add('start')
tparts = isotime().split('.')
self.start_time = tparts[0] + '.' + tparts[1][:self.precision]
def add(self, msg):
"add message point to debugtimer"
self.data.append((msg, perf_counter()))
if self.verbose:
print(msg)
def get_report(self, precision=None):
"get report text"
if precision is None:
precision = self.precision
cols = [("Message", "Delta Time (s)", "Total Time (s)")]
w0, w1, w2 = max(len(self.title), 32), 17, 17
tlast = tstart = self.data[0][1]
for msg, t in self.data:
tt = f"{t-tstart:.{precision}f}"
dt = f"{t-tlast:.{precision}f}"
tlast = t
cols.append((msg, dt, tt))
w0 = max(len(msg)+1, w0)
w1 = max(len(dt)+1, w1)
w2 = max(len(tt)+1, w2)
tline = f"+-{'-'*w0}+{'-'*w1}-+{'-'*w2}-+"
out = [f"# {self.title:{w0}s} {self.start_time:>{w1+w2}s}", tline]
for i, col in enumerate(cols):
out.append(f"| {col[0]:{w0}s}|{col[1]:>{w1}s} |{col[2]:>{w2}s} |")
if i == 0:
out.append(tline.replace('-', '='))
out.append(tline)
out.append('')
return "\n".join(out)
def show(self, precision=None, clear=True):
"print report text"
print(self.get_report(precision=precision))
if clear:
self.clear(title=self.title)
def debugtimer(title=None, precision=4, verbose=False):
'''return a DebugTimer object to measure the run time of
portions of code, and write a simple report.
Arguments
------------
title: str, optional initial message ['DebugTimer']
precision: int, precision for timing results [4]
verbose: bool, whether to print() each message when entered [False]
Returns
--------
DebugTimer object, with methods:
clear(title=None) : reset Timer
add(message) : record an event, saving message and time
get_report() : return text of report
show() : print out text of report and optionally clear
Example:
-------
timer = debugtimer('timer testing', precision=4)
result = foo(x=100)
timer.add('ran function foo')
bar(result)
timer.add('ran bar')
timer.show()
'''
return DebugTimer(title=title, precision=precision, verbose=verbose)
if __name__ == '__main__':
import numpy as np
dtimer = debugtimer('test timer')
sleep(1.1010)
dtimer.add('slept for 1.101 seconds')
nx = 10_000_000
x = np.arange(nx, dtype='float64')/3.0
dtimer.add(f'created numpy array len={nx}')
s = np.sqrt(x)
dtimer.add('took sqrt')
dtimer.show(precision=4)
|