mirror of
https://github.com/python/cpython.git
synced 2024-11-23 18:04:37 +08:00
124 lines
3.4 KiB
Python
124 lines
3.4 KiB
Python
|
"""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())
|