導引
在計算密集型計算或一些Web應用中,我們常常需要對代碼做性能分析,在Python中,最原始的方法即是使用time包中的time函式(該函式以秒為計時單位):
from time import sleep, time
def func1():
sleep(0.001)
def func2():
sleep(2)
begin1 = time()
func1()
end1 = time()
begin2 = time()
func2()
end2 = time()
print("func1 consume: %f, func2 consume:%f, func3 consume: %f"\
% (end1-begin1, end2-begin2, end2-begin1))
控制臺輸出如下:
func1 consume: 0.001271, func2 consume:2.000421, func3 consume: 2.001692
pyinstrument基本用法
但是一旦函式多了起來,這種方式顯然過于繁雜,類似C語言中的cProfile,在Python中,也有專門的性能分析工具pyinstrument(該庫非內置,需要使用conda/pip安裝),我們在復雜的專案中可以使用它來代替簡陋的time.time(),
首先來看一下基本的使用,它的使用框架如下:
from pyinstrument import Profiler
from time import sleep
def func1():
sleep(0.1)
def func2():
sleep(2)
profiler = Profiler()
profiler.start()
# 這里是你要分析的代碼,我們這里分析func1和func2兩個函式
func1()
func2()
profiler.stop()
profiler.print()
可以看到,該工具也將其成功分析出了個函式的運行時間,并為我們標紅指出了運行2s的func2函式是性能瓶頸:
如果我們進一步調低函式的運行時間:
def func3():
sleep(0.0001)
profiler = Profiler()
profiler.start()
func3()
profiler.stop()
profiler.print()
此時會顯示“No samples were recorded”,如下:

這是因為你的代碼運行時間小于了1ms,如果你仍然想分析這段代碼,你可以選擇將間隔值調到比默認的0.001(1ms)小,比如這樣:
profiler = Profiler(interval=0.0001)
此時你會發現,func3也能被檢測出來了:
此外,如果你要在瀏覽器中查看分析結果,可以使用profiler.open_in_browser()代替profiler.print()的控制臺列印輸出:
也可以使用profiler.output_html()將profile以html形式輸出,
分析Flask中的web回應性能
我們也可以對Flask應用進行性能分析,具體的用法如下:
from flask import Flask, g, make_response, request
app = Flask(__name__)
@app.before_request
def before_request():
if "profile" in request.args:
g.profiler = Profiler()
g.profiler.start()
@app.after_request
def after_request(response):
if not hasattr(g, "profiler"):
return response
g.profiler.stop()
output_html = g.profiler.output_html()
return make_response(output_html)
這樣程式會檢測每個request中的?profile引數,如果檢測到則會開始分析,在運行了profiler的request結束后,它會生成一個html輸出替代掉真實的response并回傳,
參考
- [1] https://docs.python.org/3/library/time.html?highlight=time#time.time
- [2] https://pyinstrument.readthedocs.io/en/latest/guide.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/445910.html
標籤:其他
