其實平時使用測試應用運行時間的情況 細算一下還真的很少。很久沒有做性能優化的工作,不管是cProfile還是timeit模塊都已經生疏了很久沒有使用,我在以前的文章里面有提到過cPfile的性能測試使用,但是一直沒有使用過這個更輕量級的運行時間測量庫進行過仔細實踐總結,今天就來總結一下。
從最簡單的例子開始,比如我們想測試一個列表推導式究竟要比正常寫for快多少。
import timeit foooo = """ sum = [] for i in range(1000): sum.append(i) """ print timeit.timeit(stmt="[i for i in range(1000)]", number=100000) print timeit.timeit(stmt=foooo, number=100000)
輸出:
3.79257702827
9.0510661602
不難看出,使用列表推導式要比正常使用list追加元素 通過10w次循環會快上近5.3秒左右,速度快上近三倍。
timeit 模塊抽象出了;兩個可以直接使用的方法,包了一層可以讓我們不用關心內部的實現,下面看一下模塊里面的代碼:
def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number): """Convenience function to create Timer object and call timeit method.""" return Timer(stmt, setup, timer).timeit(number) def repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number): """Convenience function to create Timer object and call repeat method.""" return Timer(stmt, setup, timer).repeat(repeat, number)
可以看到這兩個方法都是對Timer類包了一層這幾個參數:
stmt: 這個參數就是statement,可以把要進行計算時間的代碼放在里面。他可以直接接受字符串的表達式,也可以接受單個變量,也可以接受函數。
setup: 這個參數可以將stmt的環境傳進去。比如各種import和參數什么的。
timer: 這個參數一般使用不到,具體使用可以參看文檔。
Timer類下面還有repeat和timeit方法 使用也非常方便就是 timeit.timeit 和 timeit.repeat。
一個就是上面例子的timeit,一個就是repeat 其實repeat就比timeit多了一個執行Timer次數的參數。這個執行次數會以數組的形式返回每次執行的時間 like this
import timeit foooo = """ sum = [] for i in range(1000): sum.append(i) """ print timeit.repeat(stmt="[i for i in range(1000)]", repeat=2, number=100000)
輸出
[4.466734170913696, 4.255025148391724]
我們可以根據此,對所有執行時間取min最小值,平均值,最大值得到我們想要的數據。感覺還是十分方便的。
貼一個稍微進階的例子,就是用到了一下setup參數的例子,是我在測試protocol buffer python的時候的例子:
# coding: utf-8 import timeit # 初始化類 x = """ say_hi.ParseFromString(p) """ y = """ simplejson.loads(x) """ print timeit.timeit(stmt=x, setup="import say_hi_pb2;" "say_hi = say_hi_pb2.SayHi();" "say_hi.id = 13423;" "say_hi.something = 'axiba';" "say_hi.extra_info = 'xiba';" "p =say_hi.SerializeToString()", number=1000000) print timeit.timeit(stmt=y, setup="import simplejson; " "json={" "'id': 13423," "'something': 'axiba'," "'extra_info': 'xiba'," "};" "x = simplejson.dumps(json)", number=1000000
另外需要補充一點是,如果你想直接 stmt 那里執行函數。可以把函數申明在當前文件中,然后在 stmt = ‘func()’ 執行函數。然后使用 setup = ‘from __main__ import func’ 即可,如果要import 多個需要使用 setup = from __main__ import func; import simplejson'