Python 寫久了,就開始用很多好用的套件。這些套件基本上都幫我們把許多事情抽象化好了,一般來說可以很快地幫你把功能做出來,是 Python 的一大優點。但另一方面,當碰到效能上的問題時,這些複雜的抽象化反而讓人難以了解到底為什麼造成了效能上的問題。寫到這個階段,差不多就可以開始 profile 你的程式了。
主要這篇是紀錄我最近工作寫一些處理資料的程式時碰到的效能問題,還有強者我同事教我用的 qcachegrind
跟 yappi
這套 profiling 的工具。
yappi
是個 python 套件,跟 cProfile
很像,主要就是 profile 你的 code 而且把結果寫入一個檔案,接者可以用各種工具檢視它的內容。這次我同事介紹我用的是 qcachegrind
這套視覺化工具,可以把 yappi
產生的 callgrind
格式的結果作漂亮的視覺化,幫助你找出問題的所在。
安裝 yappi 與 qcahcegrind
yappi
的安裝很簡單,用 pip
就可以了:
pip install yappi
qcachegrind
的安裝比較麻煩,我在 Mac 上直接用 brew
安裝:
brew install graphviz qcachegrind
需要 graphviz
的理由主要是因為 qcachegrind
需要用它來產生精美的 call graph。
yappi 基本用法
假設 foo
是你要 profile 的對象,yappi
的基本用法大概是:
yappi.clear_stats() # clear profiler
yappi.set_clock_type('cpu')
yappi.start(builtins=True) # track builtins
foo()
yappi.stop()
stat = yappi.get_func_stats()
stat.save('callgrind.foo.prof', type='callgrind')
更新: 記得要先執行 yappi.clear_stats
,我之前忘記了,所以所有的 function 的結果都混在一起。
接者只要執行 qcachegrind
並把剛剛產生的 callgrind.foo.prof
打開:
Fancy 的 profile 結果:
我下面的程式主要是想把一些資料 group by 之後產生兩兩配對的結果,起初用 pandas
寫,不小心用的了 Series
的 __getitem__
,profile 之後發現它爆慢,最後用 funcy
重寫加速。