在分析python代碼性能瓶頸,但又不想修改源代碼的時候,ipython shell以及第三方庫提供了很多擴展工具,可以不用在代碼里面加上統計性能的裝飾器,也能很方便直觀的分析代碼性能。下面以我自己實現的一個快排代碼為例,帶你使用集中不同的性能分析工具。
def quick_sort(data, low, high):
if low >= high:
return
left, right = low, high
key = data[left]
while left < right:
while left < right and data[right] >= key:
right -= 1
data[left] = data[right]
while left < right and data[left] <= key:
left += 1
data[right] = data[left]
data[right] = key
quick_sort(data, low, left - 1)
quick_sort(data, left + 1, high)
import random
data = [random.randint(0, 1000) for _ in xrange(500)]
time
在ipython shell中,通過輸入命令%time quick_sort(data, 0, 499)就可以查看調用耗時。

其中time命令的輸出wall time是實際耗時的意思,通過簡單的耗時查看就可以得出此快排算法針對不均勻分布的數組要慢很多。
timeit
在ipython shell中,通過輸入命令%timeit -n 100 -r 5 quick_sort(data, 0, 499),就可以很方便的實現多次調用找到最短耗時。

此命令的含義就是重復100遍,每遍調用5此quick_sort,timeit會返回每遍的最短平均耗時。
line_profiler
line_profiler可以分析函數內每一行的執行時間,可以很方便的找出性能瓶頸。line_profiler不是ipython自帶工具,需要通過pip install line_profiler安裝。在ipython交互界面,通過下面方式使用:

首先需要通過%load_ext導入line_profiler, -f參數是需要分析的函數。lprun命令的參數可以通過%lprun?查看。
profile
profile和cProfile是python內置的性能分析工具。可以通過很簡單的命令分析每個函數的執行時間。

圖中的命令按照累計執行時間進行降序排列,可以較為方便的找出最為耗時的函數。如果想更為直觀的展示,還可以安裝可視化組件gprof2dot和graphviz,安裝方法如下:
pip install gprof2dot
brew install graphviz (for mac)
yum -y install graphviz (for centos)
安裝好之后再ipython shell連執行cProfile.run('quick_sort(data, 0, 499)', filename='result.out', sort='cumulative')命令將耗時分析結果導出只result.out文件中,然后在bash shell里執行命令gprof2dot -f pstats result.out | dot -Tpng -o result.png即可生成非常直觀的調用耗時圖。

當然用到的這個例子不是很好,沒有把圖像的優勢展現出來,在調用非常復雜的時候,自上而下,函數的調用關系和耗時情況一目了然。更多的使用可以查閱python官方文檔。
yappi
和profile、cProfile類似,但是yappi對於多線程有着更好的支持,profile不會區分多線程,所以結果看起來會很亂。yappi文檔連接:https://bitbucket.org/sumerc/yappi/wiki/ApiYappi
使用方法如下:
import yappi
yappi.clear_stats()
yappi.start()
quick_sort(data, 0, 499)
yappi.stop()
stats = yappi.convert2pstats(yappi.get_func_stats())
stats.sort_stats("cumulative")
stats.print_stats()
在python shell連執行這些就可以把要分析的函數按照累計執行時間排序后打印出來,當然yappi同樣可以用圖像表示,在python shell里執行stats.dump_stats('result.out')把耗時數據導出到result.out中,然后在bash shell里面執行gprof2dot -f pstats result.out | dot -Tpng -o result.png,生成圖像如下:

當然yappi.start中還可以添加一些參數是否分析多線程以及builtin函數。
