在Python中计算经过时间时的困惑?
我想比较一下Python 2.6和3.1的性能,所以我写了一个简单的程序 test.py
,这个程序会执行一些基本的耗时操作:
from time import time
start = time()
q = 2 ** 1000000000
q += 3 << 1000000000
print(q.__sizeof__(), time() - start)
但是我得到了意想不到的结果。在分别运行命令 time python2.6 test.py
和 time python3.1 test.py
后,输出结果是这样的:
(133333364, 0.37349200248718262)
real 0m35.586s
user 0m28.130s
sys 0m2.110s
还有,
133333360 0.312520027161
real 0m26.413s
user 0m17.330s
sys 0m2.190s
我原本以为这两个版本的结果在比较 time
命令的输出和程序内部的运行时间时会很接近。那这是什么原因呢?
2 个回答
可能有很多原因,比如在 sys.path
上有不同的目录和压缩文件,初始化时自动加载或执行的代码,或者平台上运行的其他进程——你的代码并不是完全独立的,也不能重复运行,因此它的结果价值不大。要测量性能,使用 python -mtimeit
会好得多,真的好得多。
编辑: 一些数字...:
$ py26 -mtimeit 'q=2**1000000000; q+=3<<1000000000'
10 loops, best of 3: 466 msec per loop
$ py31 -mtimeit 'q=2**1000000000; q+=3<<1000000000'
10 loops, best of 3: 444 msec per loop
这些准确测量了 +=
的时间(在3.1版本中稍微优化了一下,可以重复测量)。如果你想测量位移或幂运算的时间,那当然不能使用字面量(因为字面量在编译时就计算好了,而不是在运行时:这也是为什么你希望所有重要的代码都放在模块的函数中,而不是放在顶层代码或主脚本中……这样编译器可以尽可能多地做一些工作,尽管它没有什么严肃的优化;-)。例如:
$ py31 -mtimeit -s't=2' 'q=t**1000000'
10 loops, best of 3: 19.4 msec per loop
$ py31 -mtimeit -s't=3' 'q=t<<1000000'
10000 loops, best of 3: 150 usec per loop
(用你正在使用的较大右侧操作数来做这些真的太慢了,我有点不耐烦;-)。混合这些操作在测量上当然会是个悲惨的灾难,因为相对较快的操作会在混合中基本消失!-) 幸运的是,没有什么好的理由去混合——毕竟,timeit
是为了微基准测试而设计的!-)
嘿,这个问题挺有意思的,我花了一些时间才搞明白:
from time import time
start = time()
q = 2 ** 1000000000 # number literal
q += 3 << 1000000000 # still a literal
print(q.__sizeof__(), time() - start)
Python的编译器会先计算出q的值。当脚本运行时,解释器会记录时间,加载已经计算好的值,然后再记录一次时间。结果不出所料,这两次的时间差不多。
而time
则是测量整个过程(编译加运行)花了多长时间。