Python腳本性能剖析

jopen 9年前發布 | 13K 次閱讀 Python Python開發
###################
#Python腳本性能剖析
###################

cProfile/profile/hotshot用于統計Python腳本各部分執行頻率和耗費時間等統計信息,pstats可用于格式化這些信息

cProfile,屬C擴展,開銷較小,適合剖析長時間運行的Python程序,推薦使用此模塊
profile,純Python模塊,存在明顯開銷,但想對其擴展的話相對比較容易
hotshot,實驗性的C模塊,主要關注開銷最小化,現已不再被維護將來可能從Python移除
profile和cProfile接口相同,cProfile相對較新可能在某些平臺上不可用

以cProfile為例來說明Python腳本性能剖析方法
*以命令行方式使用:
$ python -m cProfile [-o output_file] [-s sort_order] myscript.py
例如:
$ python -m cProfile -o myscript.out myscript.py
之后使用pstats對結果進行格式化:
$ python -c "import pstats; p=pstats.Stats('myscript.out'); p.print_stats()"
可以在格式化時指定排序字段:
$ python -c "import pstats; p=pstats.Stats('myscript.out'); p.sort_stats('time').print_stats()"


*直接在腳本內部使用:
import cProfile
import re
cProfile.run('re.compile("foo|bar")', 'restats')

import pstats
p = pstats.Stats('restats')
#strip_dirs()移除模塊名之前的路徑信息,sort_stats(-1)按標準名(module/line/name)排序,print_stats打印統計信息
p.strip_dirs().sort_stats(-1).print_stats()
#按time排序并顯示前10行
p.sort_stats('time').print_stats(10)
#按file排序只顯示class init方法相關的統計信息
p.sort_stats('file').print_stats('__init__')
#先按time排序再按cum排序,只輸出50%,然后僅列出包含init的部分
p.sort_stats('time', 'cum').print_stats(.5, 'init')
#若想知道誰調用了上述函數可以使用
p.print_callers(.5, 'init')

*cProfile模塊說明
函數:
cProfile.run(command, filename=None, sort=-1)
cProfile.runctx(command, globals, locals, filename=None)?
類:
cProfile.Profile(timer=None, timeunit=0.0, subcalls=True, builtins=True)
cProfile.Profile類下的方法:
enable()
Start collecting profiling data.

disable()
Stop collecting profiling data.

create_stats()
Stop collecting profiling data and record the results internally as the current profile.

print_stats(sort=-1)
Create a Stats object based on the current profile and print the results to stdout.

dump_stats(filename)
Write the results of the current profile to filename.

run(cmd)
Profile the cmd via exec().

runctx(cmd, globals, locals)
Profile the cmd via exec() with the specified global and local environment.

runcall(func, *args, **kwargs)
Profile func(*args, **kwargs)

*Stats類(pstats.Stats)說明
strip_dirs()    用以除去文件名前的路徑信息。
add(filename,[…]) 把profile的輸出文件加入Stats實例中統計
dump_stats(filename) 把Stats的統計結果保存到文件
sort_stats(key,[…]) 最重要的一個函數,用以排序profile的輸出
reverse_order() 把Stats實例里的數據反序重排
print_stats([restriction,…]) 把Stats報表輸出到stdout
print_callers([restriction,…]) 輸出調用了指定的函數的函數的相關信息
print_callees([restriction,…]) 輸出指定的函數調用過的函數的相關信息

sort_stats支持以下參數:

參數 含義

'calls' call count
'cumulative' cumulative time
'cumtime' cumulative time
'file' file name
'filename' file name
'module' file name
'ncalls' call count
'pcalls' primitive call count
'line' line number
'name' function name
'nfl' name/file/line
'stdname' standard name
'time' internal time
'tottime' internal time


*一個比較典型的輸出結果:

   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次,原始調用說明不包含遞歸調用。
以standard name進行排序。3/1表示發生了遞歸調用,1為原始調用次數,3為遞歸調用次數
ncalls 函數的被調用次數
tottime 函數總計運行時間,除去函數中調用的函數運行時間
percall 函數運行一次的平均時間,等于tottime/ncalls
cumtime 函數總計運行時間,含調用的函數運行時間
percall 函數運行一次的平均時間,等于cumtime/ncalls
filename:lineno(function) 函數所在的文件名,函數的行號,函數名


參考:
https://docs.python.org/2/library/profile.html
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!