diff options
author | Skip Montanaro <skip@pobox.com> | 2003-04-09 01:38:53 (GMT) |
---|---|---|
committer | Skip Montanaro <skip@pobox.com> | 2003-04-09 01:38:53 (GMT) |
commit | ca652746ff30e4295126f024db76a5ee094a3400 (patch) | |
tree | 9ef7fd141e5b1be58e35e2f24580bc0611ad6607 | |
parent | 400d8ee6fa59bd2969c67cbd1e4f6d9663edb090 (diff) | |
download | cpython-ca652746ff30e4295126f024db76a5ee094a3400.zip cpython-ca652746ff30e4295126f024db76a5ee094a3400.tar.gz cpython-ca652746ff30e4295126f024db76a5ee094a3400.tar.bz2 |
doc for timeit module/script - mostly just a recast of Tim's docstring
-rw-r--r-- | Doc/lib/libtimeit.tex | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/Doc/lib/libtimeit.tex b/Doc/lib/libtimeit.tex new file mode 100644 index 0000000..34b21f7 --- /dev/null +++ b/Doc/lib/libtimeit.tex @@ -0,0 +1,184 @@ +\section{\module{timeit} --- + Measure execution time of small code snippets} + +\declaremodule{standard}{timeit} +\modulesynopsis{Measure the execution time of small code snippets.} + +\index{Benchmarking} +\index{Performance} + +\versionadded{2.3} + +This module provides a simple way to time small bits of Python code. It has +both command line as well as callable interfaces. It avoids a number of +common traps for measuring execution times. See also Tim Peters' +introduction to the Algorithms chapter in the ``Python Cookbook'', published +by O'Reilly. + +The module interface defines the following public class: + +\begin{classdesc}{Timer}{\optional{stmt='pass' + \optional{, setup='pass' + \optional{, timer=<timer function>}}}} +Class for timing execution speed of small code snippets. + +The constructor takes a statement to be timed, an additional statement used +for setup, and a timer function. Both statements default to 'pass'; the +timer function is platform-dependent (see the module doc string). + +To measure the execution time of the first statement, use the timeit() +method. The repeat() method is a convenience to call timeit() multiple +times and return a list of results. + +The statements may contain newlines, as long as they don't contain +multi-line string literals. + +\begin{methoddesc}{print_exc}{\optional{file=None}} +Helper to print a traceback from the timed code. + +Typical use: + +\begin{verbatim} + t = Timer(...) # outside the try/except + try: + t.timeit(...) # or t.repeat(...) + except: + t.print_exc() +\end{verbatim} + +The advantage over the standard traceback is that source lines in the +compiled template will be displayed. + +The optional file argument directs where the traceback is sent; it defaults +to \code{sys.stderr}. +\end{methoddesc} + +\begin{methoddesc}{repeat}{\optional{repeat=3\optional{, number=1000000}}} +Call \method{timeit()} a few times. + +This is a convenience function that calls the \method{timeit()} repeatedly, +returning a list of results. The first argument specifies how many times to +call \function{timeit()}. The second argument specifies the \code{number} +argument for \function{timeit()}. + +Note: it's tempting to calculate mean and standard deviation from the result +vector and report these. However, this is not very useful. In a typical +case, the lowest value gives a lower bound for how fast your machine can run +the given code snippet; higher values in the result vector are typically not +caused by variability in Python's speed, but by other processes interfering +with your timing accuracy. So the \function{min()} of the result is +probably the only number you should be interested in. After that, you +should look at the entire vector and apply common sense rather than +statistics. +\end{methoddesc} + +\begin{methoddesc}{timeit}{\optional{number=1000000}} +Time \code{number} executions of the main statement. + +To be precise, this executes the setup statement once, and then returns the +time it takes to execute the main statement a number of times, as a float +measured in seconds. The argument is the number of times through the loop, +defaulting to one million. The main statement, the setup statement and the +timer function to be used are passed to the constructor. +\end{methoddesc} +\end{classdesc} + +\subsection{Command Line Interface} + +When called as a program from the command line, the following form is used: + +\begin{verbatim} + python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...] +\end{verbatim} + +where the following options are understood: + +\begin{description} +\item[-n N/--number=N] how many times to execute 'statement' +\item[-r N/--repeat=N] how many times to repeat the timer (default 3) +\item[-s S/--setup=S] statement to be executed once initially (default +'pass') +\item[-t/--time] use time.time() (default on all platforms but Windows) +\item[-c/--clock] use time.clock() (default on Windows) +\item[-v/--verbose] print raw timing results; repeat for more digits +precision +\item[-h/--help] print a short usage message and exit +\end{description} + +A multi-line statement may be given by specifying each line as a separate +statement argument; indented lines are possible by enclosing an argument in +quotes and using leading spaces. Multiple -s options are treated similarly. + +If -n is not given, a suitable number of loops is calculated by trying +successive powers of 10 until the total time is at least 0.2 seconds. + +The default timer function is platform dependent. On Windows, clock() has +microsecond granularity but time()'s granularity is 1/60th of a second; on +Unix, clock() has 1/100th of a second granularity and time() is much more +precise. On either platform, the default timer functions measures wall +clock time, not the CPU time. This means that other processes running on +the same computer may interfere with the timing. The best thing to do when +accurate timing is necessary is to repeat the timing a few times and use the +best time. The -r option is good for this; the default of 3 repetitions is +probably enough in most cases. On Unix, you can use clock() to measure CPU +time. + +Note: there is a certain baseline overhead associated with executing a pass +statement. The code here doesn't try to hide it, but you should be aware of +it. The baseline overhead can be measured by invoking the program without +arguments. + +The baseline overhead differs between Python versions! Also, to fairly +compare older Python versions to Python 2.3, you may want to use python -O +for the older versions to avoid timing SET_LINENO instructions. + +\subsection{Examples} + +Here are two example sessions (one using the command line, one using the +module interface) that compare the cost of using \function{hasattr()} +vs. try/except to test for missing and present object attributes. + +\begin{verbatim} +\% timeit.py 'try:' ' str.__nonzero__' 'except AttributeError:' ' pass' +100000 loops, best of 3: 15.7 usec per loop +\% timeit.py 'if hasattr(str, "__nonzero__"): pass' +100000 loops, best of 3: 4.26 usec per loop +\% timeit.py 'try:' ' int.__nonzero__' 'except AttributeError:' ' pass' +1000000 loops, best of 3: 1.43 usec per loop +\% timeit.py 'if hasattr(int, "__nonzero__"): pass' +100000 loops, best of 3: 2.23 usec per loop +\end{verbatim} + +\begin{verbatim} +>>> import timeit +>>> s = """\ +... try: +... str.__nonzero__ +... except AttributeError: +... pass +... """ +>>> t = timeit.Timer(stmt=s) +>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) +17.09 usec/pass +>>> s = """\ +... if hasattr(str, '__nonzero__'): pass +... """ +>>> t = timeit.Timer(stmt=s) +>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) +4.85 usec/pass +>>> s = """\ +... try: +... int.__nonzero__ +... except AttributeError: +... pass +... """ +>>> t = timeit.Timer(stmt=s) +>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) +1.97 usec/pass +>>> s = """\ +... if hasattr(int, '__nonzero__'): pass +... """ +>>> t = timeit.Timer(stmt=s) +>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000) +3.15 usec/pass +\end{verbatim} |