3 """Tool for measuring execution time of small code snippets.
5 This module avoids a number of common traps for measuring execution
6 times. See also Tim Peters' introduction to the Algorithms chapter in
7 the Python Cookbook, published by O'Reilly.
9 Library usage: see the Timer class.
12 python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement]
15 -n/--number N: how many times to execute 'statement' (default: see below)
16 -r/--repeat N: how many times to repeat the timer (default 3)
17 -s/--setup S: statement to be executed once initially (default 'pass')
18 -t/--time: use time.time() (default on Unix)
19 -c/--clock: use time.clock() (default on Windows)
20 -v/--verbose: print raw timing results; repeat for more digits precision
21 -h/--help: print this usage message and exit
22 statement: statement to be timed (default 'pass')
24 A multi-line statement may be given by specifying each line as a
25 separate argument; indented lines are possible by enclosing an
26 argument in quotes and using leading spaces. Multiple -s options are
29 If -n is not given, a suitable number of loops is calculated by trying
30 successive powers of 10 until the total time is at least 0.2 seconds.
32 The difference in default timer function is because on Windows,
33 clock() has microsecond granularity but time()'s granularity is 1/60th
34 of a second; on Unix, clock() has 1/100th of a second granularity and
35 time() is much more precise. On either platform, the default timer
36 functions measures wall clock time, not the CPU time. This means that
37 other processes running on the same computer may interfere with the
38 timing. The best thing to do when accurate timing is necessary is to
39 repeat the timing a few times and use the best time. The -r option is
40 good for this; the default of 3 repetitions is probably enough in most
41 cases. On Unix, you can use clock() to measure CPU time.
43 Note: there is a certain baseline overhead associated with executing a
44 pass statement. The code here doesn't try to hide it, but you should
45 be aware of it. The baseline overhead can be measured by invoking the
46 program without arguments.
48 The baseline overhead differs between Python versions! Also, to
49 fairly compare older Python versions to Python 2.3, you may want to
50 use python -O for the older versions to avoid timing SET_LINENO
59 # Must be an older Python version (see timeit() below)
64 dummy_src_name
= "<timeit-src>"
65 default_number
= 1000000
68 if sys
.platform
== "win32":
69 # On Windows, the best timer is time.clock()
70 default_timer
= time
.clock
72 # On most other platforms the best timer is time.time()
73 default_timer
= time
.time
75 # Don't change the indentation of the template; the reindent() calls
76 # in Timer.__init__() depend on setup being indented 4 spaces and stmt
77 # being indented 8 spaces.
79 def inner(_it, _timer):
88 def reindent(src
, indent
):
89 """Helper to reindent a multi-line statement."""
90 return src
.replace("\n", "\n" + " "*indent
)
93 """Class for timing execution speed of small code snippets.
95 The constructor takes a statement to be timed, an additional
96 statement used for setup, and a timer function. Both statements
97 default to 'pass'; the timer function is platform-dependent (see
100 To measure the execution time of the first statement, use the
101 timeit() method. The repeat() method is a convenience to call
102 timeit() multiple times and return a list of results.
104 The statements may contain newlines, as long as they don't contain
105 multi-line string literals.
108 def __init__(self
, stmt
="pass", setup
="pass", timer
=default_timer
):
109 """Constructor. See class doc string."""
111 stmt
= reindent(stmt
, 8)
112 setup
= reindent(setup
, 4)
113 src
= template
% {'stmt': stmt
, 'setup': setup
}
114 self
.src
= src
# Save for traceback display
115 code
= compile(src
, dummy_src_name
, "exec")
117 exec code
in globals(), ns
118 self
.inner
= ns
["inner"]
120 def print_exc(self
, file=None):
121 """Helper to print a traceback from the timed code.
125 t = Timer(...) # outside the try/except
127 t.timeit(...) # or t.repeat(...)
131 The advantage over the standard traceback is that source lines
132 in the compiled template will be displayed.
134 The optional file argument directs where the traceback is
135 sent; it defaults to sys.stderr.
137 import linecache
, traceback
138 linecache
.cache
[dummy_src_name
] = (len(self
.src
),
140 self
.src
.split("\n"),
142 traceback
.print_exc(file=file)
144 def timeit(self
, number
=default_number
):
145 """Time 'number' executions of the main statement.
147 To be precise, this executes the setup statement once, and
148 then returns the time it takes to execute the main statement
149 a number of times, as a float measured in seconds. The
150 argument is the number of times through the loop, defaulting
151 to one million. The main statement, the setup statement and
152 the timer function to be used are passed to the constructor.
155 it
= itertools
.repeat(None, number
)
158 return self
.inner(it
, self
.timer
)
160 def repeat(self
, repeat
=default_repeat
, number
=default_number
):
161 """Call timeit() a few times.
163 This is a convenience function that calls the timeit()
164 repeatedly, returning a list of results. The first argument
165 specifies how many times to call timeit(), defaulting to 3;
166 the second argument specifies the timer argument, defaulting
169 Note: it's tempting to calculate mean and standard deviation
170 from the result vector and report these. However, this is not
171 very useful. In a typical case, the lowest value gives a
172 lower bound for how fast your machine can run the given code
173 snippet; higher values in the result vector are typically not
174 caused by variability in Python's speed, but by other
175 processes interfering with your timing accuracy. So the min()
176 of the result is probably the only number you should be
177 interested in. After that, you should look at the entire
178 vector and apply common sense rather than statistics.
181 for i
in range(repeat
):
182 t
= self
.timeit(number
)
187 """Main program, used when run as a script.
189 The optional argument specifies the command line to be parsed,
190 defaulting to sys.argv[1:].
192 The return value is an exit code to be passed to sys.exit(); it
193 may be None to indicate success.
195 When an exception happens during timing, a traceback is printed to
196 stderr and the return value is 1. Exceptions at other times
197 (including the template compilation) are not caught.
203 opts
, args
= getopt
.getopt(args
, "n:s:r:tcvh",
204 ["number=", "setup=", "repeat=",
205 "time", "clock", "verbose", "help"])
206 except getopt
.error
, err
:
208 print "use -h/--help for command line help"
210 timer
= default_timer
211 stmt
= "\n".join(args
) or "pass"
212 number
= 0 # auto-determine
214 repeat
= default_repeat
218 if o
in ("-n", "--number"):
220 if o
in ("-s", "--setup"):
222 if o
in ("-r", "--repeat"):
226 if o
in ("-t", "--time"):
228 if o
in ("-c", "--clock"):
230 if o
in ("-v", "--verbose"):
234 if o
in ("-h", "--help"):
237 setup
= "\n".join(setup
) or "pass"
238 # Include the current directory, so that local imports work (sys.path
239 # contains the directory of this script, rather than the current
242 sys
.path
.insert(0, os
.curdir
)
243 t
= Timer(stmt
, setup
, timer
)
245 # determine number so that 0.2 <= total time < 2.0
246 for i
in range(1, 10):
254 print "%d loops -> %.*g secs" % (number
, precision
, x
)
258 r
= t
.repeat(repeat
, number
)
264 print "raw times:", " ".join(["%.*g" % (precision
, x
) for x
in r
])
265 print "%d loops," % number
,
266 usec
= best
* 1e6
/ number
267 print "best of %d: %.*g usec per loop" % (repeat
, precision
, usec
)
270 if __name__
== "__main__":