summaryrefslogtreecommitdiff
path: root/Lib/timeit.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/timeit.py')
-rw-r--r--[-rwxr-xr-x]Lib/timeit.py73
1 files changed, 49 insertions, 24 deletions
diff --git a/Lib/timeit.py b/Lib/timeit.py
index 2de88f7271..2770efa35a 100755..100644
--- a/Lib/timeit.py
+++ b/Lib/timeit.py
@@ -207,6 +207,26 @@ class Timer:
r.append(t)
return r
+ def autorange(self, callback=None):
+ """Return the number of loops so that total time >= 0.2.
+
+ Calls the timeit method with *number* set to successive powers of
+ ten (10, 100, 1000, ...) up to a maximum of one billion, until
+ the time taken is at least 0.2 second, or the maximum is reached.
+ Returns ``(number, time_taken)``.
+
+ If *callback* is given and is not None, it will be called after
+ each trial with two arguments: ``callback(number, time_taken)``.
+ """
+ for i in range(1, 10):
+ number = 10**i
+ time_taken = self.timeit(number)
+ if callback:
+ callback(number, time_taken)
+ if time_taken >= 0.2:
+ break
+ return (number, time_taken)
+
def timeit(stmt="pass", setup="pass", timer=default_timer,
number=default_number, globals=None):
"""Convenience function to create Timer object and call timeit method."""
@@ -295,17 +315,16 @@ def main(args=None, *, _wrap_timer=None):
t = Timer(stmt, setup, timer)
if number == 0:
# 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:
- t.print_exc()
- return 1
- if verbose:
- print("%d loops -> %.*g secs" % (number, precision, x))
- if x >= 0.2:
- break
+ callback = None
+ if verbose:
+ def callback(number, time_taken):
+ msg = "{num} loops -> {secs:.{prec}g} secs"
+ print(msg.format(num=number, secs=time_taken, prec=precision))
+ try:
+ number, _ = t.autorange(callback)
+ except:
+ t.print_exc()
+ return 1
try:
r = t.repeat(repeat, number)
except:
@@ -317,20 +336,26 @@ def main(args=None, *, _wrap_timer=None):
print("%d loops," % number, end=' ')
usec = best * 1e6 / number
if time_unit is not None:
- print("best of %d: %.*g %s per loop" % (repeat, precision,
- usec/units[time_unit], time_unit))
+ scale = units[time_unit]
else:
- if usec < 1000:
- print("best of %d: %.*g usec per loop" % (repeat, precision, usec))
- else:
- msec = usec / 1000
- if msec < 1000:
- print("best of %d: %.*g msec per loop" % (repeat,
- precision, msec))
- else:
- sec = msec / 1000
- print("best of %d: %.*g sec per loop" % (repeat,
- precision, sec))
+ scales = [(scale, unit) for unit, scale in units.items()]
+ scales.sort(reverse=True)
+ for scale, time_unit in scales:
+ if usec >= scale:
+ break
+ print("best of %d: %.*g %s per loop" % (repeat, precision,
+ usec/scale, time_unit))
+ best = min(r)
+ usec = best * 1e6 / number
+ worst = max(r)
+ if worst >= best * 4:
+ usec = worst * 1e6 / number
+ import warnings
+ warnings.warn_explicit(
+ "The test results are likely unreliable. The worst\n"
+ "time (%.*g %s) was more than four times slower than the best time." %
+ (precision, usec/scale, time_unit),
+ UserWarning, '', 0)
return None
if __name__ == "__main__":