timeit
timeit - 测量小代码片段的执行时间
2.3版本的新功能。
源代码:
Lib/ timeit.py
这个模块提供了一个简单的方法来计算一小段Python代码。它既有命令行界面,也有可调用的界面。它避免了测量执行时间的一些常见陷阱。另请参阅Tim Peters在O'Reilly出版的Python Cookbook
的“算法”一章中的介绍。
1.基本例子
以下示例显示了如何使用命令行界面比较三个不同的表达式:
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
这可以通过以下Python接口来实现:
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.8187260627746582
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.7288308143615723
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.5858950614929199
但请注意,timeit
只有在使用命令行界面时,才会自动确定重复次数。在“示例”部分中,您可以找到更多高级示例。
2. Python界面
该模块定义了三个便利功能和一个公开课:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
Timer
使用给定的语句,设置
代码和计时器
函数创建一个实例,并timeit()
使用数字
执行运行它的方法。
2.6版本中的新功能。
timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
Timer
使用给定的语句,设置
代码和计时器
函数创建一个实例,并repeat()
使用给定的重复
次数
和次数
执行来运行它的方法。
2.6版本中的新功能。
timeit.default_timer()
以平台特定的方式定义默认计时器。在Windows上,time.clock()
具有微秒粒度,但time.time()
粒度为1/60秒。在Unix上,time.clock()
具有1/100秒的粒度,并且time.time()
更精确。在任一平台上,default_timer()
测量挂钟时间,而不是CPU时间。这意味着在同一台计算机上运行的其他进程可能会影响计时。
class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>)
小代码片段的定时执行速度类。
构造函数接受一个语句来定时,另外一个用于设置的语句和一个定时器函数。两个语句默认为'pass'
;
定时器功能与平台有关(请参阅模块doc字符串)。stmt
和setup
也可能包含多个由;
或换行符分隔的语句,只要它们不包含多行字符串文字。
要度量第一条语句的执行时间,请使用该timeit()
方法。该repeat()
方法可以方便地timeit()
多次调用并返回结果列表。
在版本2.6中更改:stmt
和setup
参数现在也可以使用无参数可调用的对象。这将在一个定时器函数中嵌入对它们的调用,然后由它执行timeit()
。请注意,由于额外的函数调用,在这种情况下计时开销稍大。
timeit(number=1000000)
主要语句的时间编号
执行。这会执行一次设置语句,然后返回多次执行主语句所需的时间,以秒为单位以浮点形式进行度量。论证是循环的次数,默认为100万。主语句,设置语句和要使用的计时器函数传递给构造函数。
注意
默认情况下,在计时期间timeit()
临时关闭垃圾回收。这种方法的优点是它使独立的时间更具可比性。这个缺点是GC可能是被测功能性能的重要组成部分。如果是这样,GC可以重新启用为安装
字符串中的第一条语句。例如:
timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()
repeat(repeat=3, number=1000000)
调用timeit()
几次。
这是一个方便的函数,可以timeit()
重复调用,返回结果列表。第一个参数指定要调用多少次timeit()
。第二个参数指定数字
参数timeit()
。
注意
计算结果向量的平均值和标准偏差并报告这些信息是很有吸引力的。但是,这不是很有用。在典型情况下,最低值为您的机器运行给定代码片段的速度提供了一个下限; 结果向量中较高的值通常不是由Python的速度变化引起的,而是由其他进程干扰您的定时精度造成的。因此min()
,结果可能是您应该感兴趣的唯一数字。之后,您应该查看整个向量并应用常识而不是统计。
print_exc(file=None)
助手从定时代码打印回溯。
典型用途:
t = Timer(...) # outside the try/except
try:
t.timeit(...) # or t.repeat(...)
except:
t.print_exc()
与标准回溯相比,优势在于编译模板中的源代码行将被显示。可选的文件
参数指示回溯发送的位置; 它默认为sys.stderr
。
3.命令行界面
当从命令行调用程序时,将使用以下形式:
python -m timeit [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...]
在了解以下选项的情况下:
-n N, --number=N
多少次执行'声明'
-r N, --repeat=N
重复定时器的次数(默认值3)
-s S, --setup=S
语句最初执行一次(默认pass
)
-t, --time
使用time.time()
(除Windows以外的所有平台上的默认)
-c, --clock
使用time.clock()
(在Windows上默认)
-v, --verbose
打印原始时间结果; 重复更多的数字精度
-h, --help
打印一条简短的使用信息并退出
可以通过将每行指定为单独的语句参数来给出多行语句; 通过在引号中引入参数并使用前导空格,可以缩进行。多个-s
选项的处理方式相似。
如果-n
没有给出,则通过尝试连续幂为10来计算适当数量的循环,直到总时间至少为0.2秒。
default_timer()
测量可能会受到运行在同一台机器上的其他程序的影响,所以当需要准确定时时最好的做法是重复几次定时并使用最佳时间。该-r
选项对此很有帮助; 在大多数情况下,3次重复的默认值可能就足够了。在Unix上,你可以time.clock()
用来测量CPU时间。
Note
执行通过语句会产生一定的基线开销。这里的代码并不试图隐藏它,但你应该知道它。基线开销可以通过调用没有参数的程序来衡量,并且它可能在Python版本中有所不同。另外,为了比较老的Python版本和Python 2.3,你可能希望使用Python的-O
选项(请参阅优化)来避免计时SET_LINENO
指令。
4. Examples
It is possible to provide a setup statement that is executed only once at the beginning:
$ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text'
10000000 loops, best of 3: 0.0877 usec per loop
$ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)'
1000000 loops, best of 3: 0.342 usec per loop
>>> import timeit
>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')
0.41440500499993504
>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')
1.7246671520006203
The same can be done using the Timer
class and its methods:
>>> import timeit
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
>>> t.timeit()
0.3955516149999312
>>> t.repeat()
[0.40193588800002544, 0.3960157959998014, 0.39594301399984033]
The following examples show how to time expressions that contain multiple lines. Here we compare the cost of using hasattr()
vs. try
/except
to test for missing and present object attributes:
$ python -m timeit 'try:' ' str.__nonzero__' 'except AttributeError:' ' pass'
100000 loops, best of 3: 15.7 usec per loop
$ python -m timeit 'if hasattr(str, "__nonzero__"): pass'
100000 loops, best of 3: 4.26 usec per loop
$ python -m timeit 'try:' ' int.__nonzero__' 'except AttributeError:' ' pass'
1000000 loops, best of 3: 1.43 usec per loop
$ python -m timeit 'if hasattr(int, "__nonzero__"): pass'
100000 loops, best of 3: 2.23 usec per loop
>>> import timeit
>>> # attribute is missing
>>> s = """\
... try:
... str.__nonzero__
... except AttributeError:
... pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.9138244460009446
>>> s = "if hasattr(str, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.5829014980008651
>>>
>>> # attribute is present
>>> s = """\
... try:
... int.__nonzero__
... except AttributeError:
... pass
... """
>>> timeit.timeit(stmt=s, number=100000)
0.04215312199994514
>>> s = "if hasattr(int, '__bool__'): pass"
>>> timeit.timeit(stmt=s, number=100000)
0.08588060699912603
To give the timeit
module access to functions you define, you can pass a setup
parameter which contains an import statement:
def test():
"""Stupid test function"""
L = []
for i in range(100):
L.append(i)
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
© 2001–2017 Python Software Foundation
Licensed under the PSF License.