PyXR

c:\python24\lib \ timeit.py



0001 #! /usr/bin/env python
0002 
0003 """Tool for measuring execution time of small code snippets.
0004 
0005 This module avoids a number of common traps for measuring execution
0006 times.  See also Tim Peters' introduction to the Algorithms chapter in
0007 the Python Cookbook, published by O'Reilly.
0008 
0009 Library usage: see the Timer class.
0010 
0011 Command line usage:
0012     python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement]
0013 
0014 Options:
0015   -n/--number N: how many times to execute 'statement' (default: see below)
0016   -r/--repeat N: how many times to repeat the timer (default 3)
0017   -s/--setup S: statement to be executed once initially (default 'pass')
0018   -t/--time: use time.time() (default on Unix)
0019   -c/--clock: use time.clock() (default on Windows)
0020   -v/--verbose: print raw timing results; repeat for more digits precision
0021   -h/--help: print this usage message and exit
0022   statement: statement to be timed (default 'pass')
0023 
0024 A multi-line statement may be given by specifying each line as a
0025 separate argument; indented lines are possible by enclosing an
0026 argument in quotes and using leading spaces.  Multiple -s options are
0027 treated similarly.
0028 
0029 If -n is not given, a suitable number of loops is calculated by trying
0030 successive powers of 10 until the total time is at least 0.2 seconds.
0031 
0032 The difference in default timer function is because on Windows,
0033 clock() has microsecond granularity but time()'s granularity is 1/60th
0034 of a second; on Unix, clock() has 1/100th of a second granularity and
0035 time() is much more precise.  On either platform, the default timer
0036 functions measure wall clock time, not the CPU time.  This means that
0037 other processes running on the same computer may interfere with the
0038 timing.  The best thing to do when accurate timing is necessary is to
0039 repeat the timing a few times and use the best time.  The -r option is
0040 good for this; the default of 3 repetitions is probably enough in most
0041 cases.  On Unix, you can use clock() to measure CPU time.
0042 
0043 Note: there is a certain baseline overhead associated with executing a
0044 pass statement.  The code here doesn't try to hide it, but you should
0045 be aware of it.  The baseline overhead can be measured by invoking the
0046 program without arguments.
0047 
0048 The baseline overhead differs between Python versions!  Also, to
0049 fairly compare older Python versions to Python 2.3, you may want to
0050 use python -O for the older versions to avoid timing SET_LINENO
0051 instructions.
0052 """
0053 
0054 import gc
0055 import sys
0056 import time
0057 try:
0058     import itertools
0059 except ImportError:
0060     # Must be an older Python version (see timeit() below)
0061     itertools = None
0062 
0063 __all__ = ["Timer"]
0064 
0065 dummy_src_name = "<timeit-src>"
0066 default_number = 1000000
0067 default_repeat = 3
0068 
0069 if sys.platform == "win32":
0070     # On Windows, the best timer is time.clock()
0071     default_timer = time.clock
0072 else:
0073     # On most other platforms the best timer is time.time()
0074     default_timer = time.time
0075 
0076 # Don't change the indentation of the template; the reindent() calls
0077 # in Timer.__init__() depend on setup being indented 4 spaces and stmt
0078 # being indented 8 spaces.
0079 template = """
0080 def inner(_it, _timer):
0081     %(setup)s
0082     _t0 = _timer()
0083     for _i in _it:
0084         %(stmt)s
0085     _t1 = _timer()
0086     return _t1 - _t0
0087 """
0088 
0089 def reindent(src, indent):
0090     """Helper to reindent a multi-line statement."""
0091     return src.replace("\n", "\n" + " "*indent)
0092 
0093 class Timer:
0094     """Class for timing execution speed of small code snippets.
0095 
0096     The constructor takes a statement to be timed, an additional
0097     statement used for setup, and a timer function.  Both statements
0098     default to 'pass'; the timer function is platform-dependent (see
0099     module doc string).
0100 
0101     To measure the execution time of the first statement, use the
0102     timeit() method.  The repeat() method is a convenience to call
0103     timeit() multiple times and return a list of results.
0104 
0105     The statements may contain newlines, as long as they don't contain
0106     multi-line string literals.
0107     """
0108 
0109     def __init__(self, stmt="pass", setup="pass", timer=default_timer):
0110         """Constructor.  See class doc string."""
0111         self.timer = timer
0112         stmt = reindent(stmt, 8)
0113         setup = reindent(setup, 4)
0114         src = template % {'stmt': stmt, 'setup': setup}
0115         self.src = src # Save for traceback display
0116         code = compile(src, dummy_src_name, "exec")
0117         ns = {}
0118         exec code in globals(), ns
0119         self.inner = ns["inner"]
0120 
0121     def print_exc(self, file=None):
0122         """Helper to print a traceback from the timed code.
0123 
0124         Typical use:
0125 
0126             t = Timer(...)       # outside the try/except
0127             try:
0128                 t.timeit(...)    # or t.repeat(...)
0129             except:
0130                 t.print_exc()
0131 
0132         The advantage over the standard traceback is that source lines
0133         in the compiled template will be displayed.
0134 
0135         The optional file argument directs where the traceback is
0136         sent; it defaults to sys.stderr.
0137         """
0138         import linecache, traceback
0139         linecache.cache[dummy_src_name] = (len(self.src),
0140                                            None,
0141                                            self.src.split("\n"),
0142                                            dummy_src_name)
0143         traceback.print_exc(file=file)
0144 
0145     def timeit(self, number=default_number):
0146         """Time 'number' executions of the main statement.
0147 
0148         To be precise, this executes the setup statement once, and
0149         then returns the time it takes to execute the main statement
0150         a number of times, as a float measured in seconds.  The
0151         argument is the number of times through the loop, defaulting
0152         to one million.  The main statement, the setup statement and
0153         the timer function to be used are passed to the constructor.
0154         """
0155         if itertools:
0156             it = itertools.repeat(None, number)
0157         else:
0158             it = [None] * number
0159         gcold = gc.isenabled()
0160         gc.disable()
0161         timing = self.inner(it, self.timer)
0162         if gcold:
0163             gc.enable()
0164         return timing
0165 
0166     def repeat(self, repeat=default_repeat, number=default_number):
0167         """Call timeit() a few times.
0168 
0169         This is a convenience function that calls the timeit()
0170         repeatedly, returning a list of results.  The first argument
0171         specifies how many times to call timeit(), defaulting to 3;
0172         the second argument specifies the timer argument, defaulting
0173         to one million.
0174 
0175         Note: it's tempting to calculate mean and standard deviation
0176         from the result vector and report these.  However, this is not
0177         very useful.  In a typical case, the lowest value gives a
0178         lower bound for how fast your machine can run the given code
0179         snippet; higher values in the result vector are typically not
0180         caused by variability in Python's speed, but by other
0181         processes interfering with your timing accuracy.  So the min()
0182         of the result is probably the only number you should be
0183         interested in.  After that, you should look at the entire
0184         vector and apply common sense rather than statistics.
0185         """
0186         r = []
0187         for i in range(repeat):
0188             t = self.timeit(number)
0189             r.append(t)
0190         return r
0191 
0192 def main(args=None):
0193     """Main program, used when run as a script.
0194 
0195     The optional argument specifies the command line to be parsed,
0196     defaulting to sys.argv[1:].
0197 
0198     The return value is an exit code to be passed to sys.exit(); it
0199     may be None to indicate success.
0200 
0201     When an exception happens during timing, a traceback is printed to
0202     stderr and the return value is 1.  Exceptions at other times
0203     (including the template compilation) are not caught.
0204     """
0205     if args is None:
0206         args = sys.argv[1:]
0207     import getopt
0208     try:
0209         opts, args = getopt.getopt(args, "n:s:r:tcvh",
0210                                    ["number=", "setup=", "repeat=",
0211                                     "time", "clock", "verbose", "help"])
0212     except getopt.error, err:
0213         print err
0214         print "use -h/--help for command line help"
0215         return 2
0216     timer = default_timer
0217     stmt = "\n".join(args) or "pass"
0218     number = 0 # auto-determine
0219     setup = []
0220     repeat = default_repeat
0221     verbose = 0
0222     precision = 3
0223     for o, a in opts:
0224         if o in ("-n", "--number"):
0225             number = int(a)
0226         if o in ("-s", "--setup"):
0227             setup.append(a)
0228         if o in ("-r", "--repeat"):
0229             repeat = int(a)
0230             if repeat <= 0:
0231                 repeat = 1
0232         if o in ("-t", "--time"):
0233             timer = time.time
0234         if o in ("-c", "--clock"):
0235             timer = time.clock
0236         if o in ("-v", "--verbose"):
0237             if verbose:
0238                 precision += 1
0239             verbose += 1
0240         if o in ("-h", "--help"):
0241             print __doc__,
0242             return 0
0243     setup = "\n".join(setup) or "pass"
0244     # Include the current directory, so that local imports work (sys.path
0245     # contains the directory of this script, rather than the current
0246     # directory)
0247     import os
0248     sys.path.insert(0, os.curdir)
0249     t = Timer(stmt, setup, timer)
0250     if number == 0:
0251         # determine number so that 0.2 <= total time < 2.0
0252         for i in range(1, 10):
0253             number = 10**i
0254             try:
0255                 x = t.timeit(number)
0256             except:
0257                 t.print_exc()
0258                 return 1
0259             if verbose:
0260                 print "%d loops -> %.*g secs" % (number, precision, x)
0261             if x >= 0.2:
0262                 break
0263     try:
0264         r = t.repeat(repeat, number)
0265     except:
0266         t.print_exc()
0267         return 1
0268     best = min(r)
0269     if verbose:
0270         print "raw times:", " ".join(["%.*g" % (precision, x) for x in r])
0271     print "%d loops," % number,
0272     usec = best * 1e6 / number
0273     if usec < 1000:
0274         print "best of %d: %.*g usec per loop" % (repeat, precision, usec)
0275     else:
0276         msec = usec / 1000
0277         if msec < 1000:
0278             print "best of %d: %.*g msec per loop" % (repeat, precision, msec)
0279         else:
0280             sec = msec / 1000
0281             print "best of %d: %.*g sec per loop" % (repeat, precision, sec)
0282     return None
0283 
0284 if __name__ == "__main__":
0285     sys.exit(main())
0286 

Generated by PyXR 0.9.4
SourceForge.net Logo