A flexible utility to time the execution speed of a code snippet.

Usable from the command line or from a program.
This commit is contained in:
Guido van Rossum 2003-03-05 23:31:58 +00:00
parent 5b73385195
commit b3f09d4331
1 changed files with 123 additions and 0 deletions

123
Lib/timeit.py Normal file
View File

@ -0,0 +1,123 @@
"""Framework for timing execution speed of small code snippets.
This avoids a number of common traps for timing frameworks (see also
Tim Peters' introduction to the timing chapter in the Python
Cookbook).
(To use this with older versions of Python, the dependency on the
itertools module is easily removed; instead of itertools.repeat(None,
count) you can use [None]*count; this is barely slower.)
Command line usage:
python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [statement]
Options:
-n/--number N: how many times to execute 'statement' (default varies)
-r/--repeat N: how many times to repeat the timer (default 1)
-s/--setup S: statements executed once before 'statement' (default 'pass')
-t/--time: use time.time() (default on Unix)
-c/--clock: use time.clock() (default on Windows)
statement: statement to be timed (default 'pass')
"""
import sys
import math
import time
import itertools
__all__ = ["Timer"]
default_number = 1000000
default_repeat = 10
if sys.platform == "win32":
# On Windows, the best timer is time.clock()
default_timer = time.clock
else:
# On most other platforms the best timer is time.time()
default_timer = time.time
template = """
def inner(number, timer):
%(setup)s
seq = itertools.repeat(None, number)
t0 = timer()
for i in seq:
%(stmt)s
t1 = timer()
return t1-t0
"""
def reindent(src, indent):
return ("\n" + " "*indent).join(src.split("\n"))
class Timer:
def __init__(self, stmt="pass", setup="pass", timer=default_timer):
self.timer = timer
stmt = reindent(stmt, 8)
setup = reindent(setup, 4)
src = template % {'stmt': stmt, 'setup': setup}
code = compile(src, "<src>", "exec")
ns = {}
exec code in globals(), ns
self.inner = ns["inner"]
def timeit(self, number=default_number):
return self.inner(number, self.timer)
def repeat(self, repeat=default_repeat, number=default_number):
r = []
for i in range(repeat):
t = self.timeit(number)
r.append(t)
return r
def main(args=None):
if args is None:
args = sys.argv[1:]
import getopt
try:
opts, args = getopt.getopt(args, "n:s:r:tc",
["number=", "setup=", "repeat=",
"time", "clock"])
except getopt.error, err:
print err
return 2
timer = default_timer
stmt = "\n".join(args) or "pass"
number = 0 # auto-determine
setup = "pass"
repeat = 1
for o, a in opts:
if o in ("-n", "--number"):
number = int(a)
if o in ("-s", "--setup"):
setup = a
if o in ("-r", "--repeat"):
repeat = int(a)
if repeat <= 0:
repeat = 1
if o in ("-t", "time"):
timer = time.time
if o in ("-c", "clock"):
timer = time.clock
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
x = t.timeit(number)
if x >= 0.2:
break
r = t.repeat(repeat, number)
best = min(r)
print "%d loops," % number,
usec = best * 1e6 / number
if repeat > 1:
print "best of %d: %.3f usec" % (repeat, usec)
else:
print "time: %.3f usec" % usec
if __name__ == "__main__":
sys.exit(main())