感謝 ptt python 板友 sbr 指正:
※ 引述《sbrhsieh (sbr)》...
: 依照上述的碼來說,依照 Python 2.5.4 內附的 timeit module 的設計來看,test2
: 與 test3 重複執行多次,會導致 testit module loaded 後 al 參考的 list object
: 一直作串接動作而變長(長度超過 100M)。
: 重複跑 test2 與 test3 會比 test1 多許多記憶體配置與 memory copy 的操作,
: 我不認為你跑出來的量測結果是合理的(test2/test3 應該比 test1 慢上許多)。
原文中的程式碼有如下問題:global is evil XD
先看看原來程式碼的問題,我們加上下面的程式碼:
run_print_len = '''
import sys
import testit
print >> sys.stderr, 'len(al):', len(testit.al), 'len(bl):', len(testit.bl)
'''
...(原來的code)
if __name__ == '__main__':
...(原來的code)
pl = timeit.Timer(run_print_len) # 新增這兩行
pl.timeit(number=1) #
得到
% python2.5 testit.py
0.00002924 sec/pass
0.00002564 sec/pass
0.00002465 sec/pass
len(al): 200001000 len(bl): 1000
可以看到 al list 的長度非常之長,都快跟我一樣長了 XD (誤),因為每次對 testit.al 所作的改變都會繼續被下一個 test 使用。這樣的測試造成 al 在每個 test 的長度都不同,可能造成測試的不準確。
如 sbr 所述,記憶體可能需要重新配置之類的 (不過在我的環境好像沒有影響?)
import timeit
run_test1 = '''
import testit
al, bl = testit.generate_albl()
al = testit.test1(al, bl)
'''
run_test2 = '''
import testit
al, bl = testit.generate_albl()
al = testit.test2(al, bl)
'''
run_test3 = '''
import testit
al, bl = testit.generate_albl()
al = testit.test3(al, bl)
'''
run_print_len = '''
import sys
import testit
al, bl = testit.generate_albl()
print >> sys.stderr, 'len(al):', len(al), 'len(bl):', len(bl)
'''
def generate_albl():
al = [1]*1000
bl = [999]*1000
return al, bl
def test1(al, bl):
al = al + bl
return al
def test2(al, bl):
al.extend(bl)
return al
def test3(al, bl):
al += bl
return al
if __name__ == '__main__':
times = 100000
t1 = timeit.Timer(run_test1)
print "%.8f sec/pass" % (t1.timeit(number=times)/times)
t2 = timeit.Timer(run_test2)
print "%.8f sec/pass" % (t2.timeit(number=times)/times)
t3 = timeit.Timer(run_test3)
print "%.8f sec/pass" % (t3.timeit(number=times)/times)
pl = timeit.Timer(run_print_len)
pl.timeit(number=1)
修正後的結果:
Python 2.5.4 (r254:67917, Dec 23 2008, 14:57:27)
[GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
% python2.5 testit.py
0.00005440 sec/pass
0.00004385 sec/pass
0.00004388 sec/pass
len(al): 1000 len(bl): 1000