拿來主義:
python -m cProfile -o profile.pstats to_profile.py gprof2dot -f pstats profile.pstats |dot -Tpng -o click.png
然后順着淺色線條優化就OK了。
windows下:
google下graphviz-2.38.msi,然后安裝。dot命令需要。
git clone https://github.com/jrfonseca/gprof2dot.git。
然后就是:
D:\KwDownload\gprof2dot-master\gprof2dot-master>python gprof2dot.py -f pstats C:\Users\l00379637\AppData\Roaming\eSpace_Desktop\UserData\l00379637\ReceiveFile\profile.pstats | "c:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tpng -o cli ck.png
Python 優化第一步: 性能分析實踐
Python的性能分析器
Python中最常用的性能分析工具主要有:cProfiler, line_profiler以及memory_profiler等。他們以不同的方式幫助我們分析Python代碼的性能。我們這里主要關注Python內置的cProfiler,並使用它幫助我們分析並優化程序。
cProfiler
快速使用
這里我先拿上官方文檔的一個簡單例子來對cProfiler的簡單使用進行簡單介紹。
1
2
3
|
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
|
分析結果:
1
2
3
4
5
6
7
8
9
10
|
197 function calls (192 primitive calls) in 0.002 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
1 0.000 0.000 0.001 0.001 re.py:212(compile)
1 0.000 0.000 0.001 0.001 re.py:268(_compile)
1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset)
1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset)
4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction)
3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
|
從分析報告結果中我們可以得到很多信息:
- 整個過程一共有197個函數調用被監控,其中192個是原生調用(即不涉及遞歸調用)
- 總共執行的時間為0.002秒
- 結果列表中是按照標准名稱進行排序,也就是按照字符串的打印方式(數字也當作字符串)
- 在列表中:
ncalls
表示函數調用的次數(有兩個數值表示有遞歸調用,總調用次數/原生調用次數)tottime
是函數內部調用時間(不包括他自己調用的其他函數的時間)percall
等於tottime
/ncalls
cumtime
累積調用時間,與tottime相反,它包含了自己內部調用函數的時間- 最后一列,文件名,行號,函數名
優雅的使用
Python給我們提供了很多接口方便我們能夠靈活的進行性能分析,其中主要包含兩個類cProfile模塊的Profile
類和pstat模塊的Stats
類。
我們可以通過這兩個類來將代碼分析的功能進行封裝以便在項目的其他地方能夠靈活重復的使用進行分析。
這里還是需要對Profile
以及Stats
的幾個常用接口進行簡單總結:
Profile
類:
enable()
: 開始收集性能分析數據disable()
: 停止收集性能分析數據create_stats()
: 停止收集分析數據,並為已收集的數據創建stats
對象print_stats()
: 創建stats對象並打印分析結果dump_stats(filename)
: 把當前性能分析的結果寫入文件(二進制格式)runcall(func, *args, **kwargs)
: 收集被調用函數func
的性能分析數據Stats
類
pstats模塊提供的Stats
類可以幫助我們讀取和操作stats文件(二進制格式)
1
2
|
import pstats
p = pstats.Stats('stats.prof')
|
Stats
類可以接受stats文件名,也可以直接接受cProfile.Profile
對象作為數據源。strip_dirs()
: 刪除報告中所有函數文件名的路徑信息dump_stats(filename)
: 把stats中的分析數據寫入文件(效果同cProfile.Profile.dump_stats()
)sort_stats(*keys)
: 對報告列表進行排序,函數會依次按照傳入的參數排序,關鍵詞包括calls
,cumtime
等,具體參數參見https://docs.python.org/2/library/profile.html#pstats.Stats.sort_statsreverse_order()
: 逆反當前的排序print_stats(*restrictions)
: 把信息打印到標准輸出。*restrictions
用於控制打印結果的形式, 例如(10, 1.0, ".*.py.*")
表示打印所有py文件的信息的前10行結果。
分析數據可視化
gprof2dot
Gprof2Dot可將多種Profiler的數據轉成Graphviz可處理的圖像表述。配合dot命令,即可得到不同函數所消耗的時間分析圖。具體使用方法詳見: https://github.com/jrfonseca/gprof2dot
因此我們可以利用它來為我們的程序生成分析圖:
1
|
gprof2dot -f pstats mkm_run.prof | dot -Tpng -o mkm_run.png
|
於是我們路徑下面就生成了mkm_run.png
我倒是蠻喜歡這個時間分析圖,順着淺色方格的看下去很容易發現程序的瓶頸部分,
每個node的信息如下:
1
2
3
4
5
|
+------------------------------+
| function name |
| total time % ( self time % ) |
| total calls |
+------------------------------+
|
每個edge的信息如下:
1
2
3
|
total time %
calls
parent --------------------> children
|