mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
171 lines
6.0 KiB
Python
171 lines
6.0 KiB
Python
import functools
|
|
import math
|
|
import sys
|
|
import timeit
|
|
|
|
def TimeitWrapper(*args, **kwargs):
|
|
"""
|
|
This decorator @TimeitWrapper() prints the function name and execution time in seconds.
|
|
:param args:
|
|
:param kwargs:
|
|
:return:
|
|
"""
|
|
|
|
def decorator(function):
|
|
@functools.wraps(function)
|
|
def wrapper(*args, **kwargs):
|
|
start = timeit.default_timer()
|
|
results = function(*args, **kwargs)
|
|
end = timeit.default_timer()
|
|
print('{} execution time: {:.10f} s'.format(function.__name__, end - start))
|
|
return results
|
|
|
|
return wrapper
|
|
|
|
return decorator
|
|
|
|
|
|
class TimeitResult(object):
|
|
"""
|
|
from https://github.com/ipython/ipython/blob/339c0d510a1f3cb2158dd8c6e7f4ac89aa4c89d8/IPython/core/magics/execution.py#L55
|
|
|
|
Object returned by the timeit magic with info about the run.
|
|
Contains the following attributes :
|
|
loops: (int) number of loops done per measurement
|
|
repeat: (int) number of times the measurement has been repeated
|
|
best: (float) best execution time / number
|
|
all_runs: (list of float) execution time of each run (in s)
|
|
"""
|
|
|
|
def __init__(self, loops, repeat, best, worst, all_runs, precision):
|
|
self.loops = loops
|
|
self.repeat = repeat
|
|
self.best = best
|
|
self.worst = worst
|
|
self.all_runs = all_runs
|
|
self._precision = precision
|
|
self.timings = [dt / self.loops for dt in all_runs]
|
|
|
|
@property
|
|
def average(self):
|
|
return math.fsum(self.timings) / len(self.timings)
|
|
|
|
@property
|
|
def stdev(self):
|
|
mean = self.average
|
|
return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
|
|
|
|
def __str__(self):
|
|
pm = '+-'
|
|
if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
|
|
try:
|
|
u'\xb1'.encode(sys.stdout.encoding)
|
|
pm = u'\xb1'
|
|
except:
|
|
pass
|
|
return "min:{best} max:{worst} mean:{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
|
|
pm=pm,
|
|
runs=self.repeat,
|
|
loops=self.loops,
|
|
loop_plural="" if self.loops == 1 else "s",
|
|
run_plural="" if self.repeat == 1 else "s",
|
|
mean=format_time(self.average, self._precision),
|
|
std=format_time(self.stdev, self._precision),
|
|
best=format_time(self.best, self._precision),
|
|
worst=format_time(self.worst, self._precision),
|
|
)
|
|
|
|
def _repr_pretty_(self, p, cycle):
|
|
unic = self.__str__()
|
|
p.text(u'<TimeitResult : ' + unic + u'>')
|
|
|
|
|
|
class FPSResult(object):
|
|
"""
|
|
base https://github.com/ipython/ipython/blob/339c0d510a1f3cb2158dd8c6e7f4ac89aa4c89d8/IPython/core/magics/execution.py#L55
|
|
"""
|
|
|
|
def __init__(self, loops, repeat, best, worst, all_runs, precision):
|
|
self.loops = loops
|
|
self.repeat = repeat
|
|
self.best = 1 / best
|
|
self.worst = 1 / worst
|
|
self.all_runs = all_runs
|
|
self._precision = precision
|
|
self.fps = [1 / dt for dt in all_runs]
|
|
self.unit = "fps"
|
|
|
|
@property
|
|
def average(self):
|
|
return math.fsum(self.fps) / len(self.fps)
|
|
|
|
@property
|
|
def stdev(self):
|
|
mean = self.average
|
|
return (math.fsum([(x - mean) ** 2 for x in self.fps]) / len(self.fps)) ** 0.5
|
|
|
|
def __str__(self):
|
|
pm = '+-'
|
|
if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
|
|
try:
|
|
u'\xb1'.encode(sys.stdout.encoding)
|
|
pm = u'\xb1'
|
|
except:
|
|
pass
|
|
return "min:{best} max:{worst} mean:{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
|
|
pm=pm,
|
|
runs=self.repeat,
|
|
loops=self.loops,
|
|
loop_plural="" if self.loops == 1 else "s",
|
|
run_plural="" if self.repeat == 1 else "s",
|
|
mean="%.*g%s" % (self._precision, self.average, self.unit),
|
|
std="%.*g%s" % (self._precision, self.stdev, self.unit),
|
|
best="%.*g%s" % (self._precision, self.best, self.unit),
|
|
worst="%.*g%s" % (self._precision, self.worst, self.unit),
|
|
)
|
|
|
|
def _repr_pretty_(self, p, cycle):
|
|
unic = self.__str__()
|
|
p.text(u'<FPSResult : ' + unic + u'>')
|
|
|
|
|
|
def format_time(timespan, precision=3):
|
|
"""
|
|
https://github.com/ipython/ipython/blob/339c0d510a1f3cb2158dd8c6e7f4ac89aa4c89d8/IPython/core/magics/execution.py#L1473
|
|
Formats the timespan in a human readable form
|
|
"""
|
|
|
|
if timespan >= 60.0:
|
|
# we have more than a minute, format that in a human readable form
|
|
# Idea from http://snipplr.com/view/5713/
|
|
parts = [("d", 60 * 60 * 24), ("h", 60 * 60), ("min", 60), ("s", 1)]
|
|
time = []
|
|
leftover = timespan
|
|
for suffix, length in parts:
|
|
value = int(leftover / length)
|
|
if value > 0:
|
|
leftover = leftover % length
|
|
time.append(u'%s%s' % (str(value), suffix))
|
|
if leftover < 1:
|
|
break
|
|
return " ".join(time)
|
|
|
|
# Unfortunately the unicode 'micro' symbol can cause problems in
|
|
# certain terminals.
|
|
# See bug: https://bugs.launchpad.net/ipython/+bug/348466
|
|
# Try to prevent crashes by being more secure than it needs to
|
|
# E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
|
|
units = [u"s", u"ms", u'us', "ns"] # the save value
|
|
if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
|
|
try:
|
|
u'\xb5'.encode(sys.stdout.encoding)
|
|
units = [u"s", u"ms", u'\xb5s', "ns"]
|
|
except:
|
|
pass
|
|
scaling = [1, 1e3, 1e6, 1e9]
|
|
|
|
if timespan > 0.0:
|
|
order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
|
|
else:
|
|
order = 3
|
|
return u"%.*g %s" % (precision, timespan * scaling[order], units[order]) |