Python使用cProfile分析和定位應(yīng)用性能瓶頸點
一、需求背景
性能壓測時,發(fā)現(xiàn)某接口存在性能瓶頸,期望借助工具定位該瓶頸,最好能定位至具體慢方法。
二、cProfile 簡介
cProfile 是 Python 標準庫中的一個模塊,用于對 Python 程序進行性能分析,它能輸出每個函數(shù)的調(diào)用次數(shù)、執(zhí)行耗時等詳細信息,可幫助開發(fā)者識別程序中運行緩慢的方法,以便進行性能優(yōu)化,適合作為上述需求的解決方案。
此外,Python 還內(nèi)置了使用純 Python 實現(xiàn)的 profile 模塊,與 cProfile 功能一樣,只不過 cProfile 是用 C 語言編寫,性能更高、開銷更小,適合在性能敏感的環(huán)境(如線上生產(chǎn)環(huán)境)中使用。profile 是純 Python 實現(xiàn)的模塊,性能開銷相對較大,但因其用 Python 編寫,易于理解和修改,適合學(xué)習(xí)時使用。
三、使用方法
cProfile 支持三種使用方法,一是硬編碼于代碼中;二是在 Python 應(yīng)用啟動時加載 cProfile 模塊;三是通過 IDE(PyCharm)運行。開發(fā)環(huán)境建議采用方法三,因其簡單易用且結(jié)果圖表豐富;生產(chǎn)環(huán)境建議采用方法二,此方法對代碼無侵入性。
1. 硬編碼于代碼中
示例代碼:
import cProfile def my_function(): # Some code to profile pass profiler = cProfile.Profile() profiler.enable() my_function() profiler.disable() profiler.print_stats()
執(zhí)行結(jié)果:
2 function calls in 0.000 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 test.py:3(my_function)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
結(jié)果字段說明:
ncalls:函數(shù)調(diào)用的次數(shù)。
tottime:在該函數(shù)中花費的總時間,不包括調(diào)用子函數(shù)的時間。
percall:tottime 除以 ncalls。
cumtime:該函數(shù)及其所有子函數(shù)中花費的總時間。
percall:cumtime 除以原始調(diào)用次數(shù)。
filename:lineno(function):函數(shù)所在的文件名、行號和函數(shù)名。
2. 在 Python 應(yīng)用啟動時加載 cProfile 模塊
示例代碼:
python -m cProfile my_script.py # 方法一、將結(jié)果輸出至控制臺 python -m cProfile -o output.prof my_script.py # 方法二、將結(jié)果保存到指定的prof文件
可使用 snakeviz 插件(安裝方法為pip install snakeviz
)分析 prof 文件。執(zhí)行snakeviz output.prof
后,會將結(jié)果掛載到 web 容器中,支持通過 URL(如http://127.0.0.1:8080/snakeviz/xxxoutput.prof
)訪問。
3. 通過 IDE(PyCharm)運行
使用方法:
通過菜單 [run] > [profile 'app'](其中 app 為應(yīng)用名稱,下同)啟動應(yīng)用。待應(yīng)用執(zhí)行完畢且停止后,相關(guān)面板會輸出相應(yīng)的調(diào)用統(tǒng)計與調(diào)用鏈。
調(diào)用統(tǒng)計:
表頭“Name”表示被調(diào)用的模塊或函數(shù);“Call Count”表示被調(diào)用次數(shù);“Time (ms)”表示耗時及百分比,時間單位為毫秒。
點擊表頭列名可對該列進行排序。
在調(diào)用統(tǒng)計中,選擇“name”列的單元格,右鍵選中“Navigate to Source”或“Show on Call Graph”,可打開其源碼或?qū)?yīng)的調(diào)用鏈及位置。
調(diào)用鏈:
此外,通過菜單 [run] > [Concurrency Diagram 'app'] 啟動程序,可查看到線程和異步協(xié)程(Asyncio)的調(diào)用情況,如下圖所示:
四、相關(guān)配置項
1. cProfile
[root@test bin]# python3 -m cProfile -h Usage: cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ... Options: -h, --help show this help message and exit -o OUTFILE, --outfile=OUTFILE Save stats to <outfile> # 將分析結(jié)果輸出到指定的文件中。 -s SORT, --sort=SORT Sort order when printing to stdout, based on pstats.Stats class # 指定輸出結(jié)果的排序方式??梢愿鶕?jù)不同的字段進行排序,如 time, cumulative, calls 等。 -m Profile a library module # 分析一個模塊,而不是一個腳本文件
2. snakeviz
[root@test bin]# snakeviz --help usage: snakeviz [-h] [-v] [-H ADDR] [-p PORT] [-b BROWSER_PATH] [-s] filename Start SnakeViz to view a Python profile. positional arguments: filename Python profile to view options: -h, --help show this help message and exit -v, --version show program \`s version number and exit -H ADDR, --hostname ADDR hostname to bind to (default: 127.0.0.1) # 用于指定綁定的主機名,默認值為 127.0.0.1,即本地主機。 -p PORT, --port PORT port to bind to; if this port is already in use a free port will be selected automatically (default: 8080) # 用于指定綁定的端口。如果指定的端口已被占用,程序?qū)⒆詣舆x擇一個空閑端口。默認值為 8080。 -b BROWSER_PATH, --browser BROWSER_PATH name of webbrowser to launch as described in the documentation of Python\'s webbrowser module: https://docs.python.org/3/library/webbrowser.html # 按照 Python 的 webbrowser 模塊的文檔描述,指定要啟動的瀏覽器名稱。用戶可以通過指定瀏覽器的路徑來控制使用哪個瀏覽器打開應(yīng)用。 -s, --server start SnakeViz in server-only mode--no attempt will be made to open a browser # 僅在服務(wù)器模式下啟動 SnakeViz,不會嘗試打開服務(wù)器中的瀏覽器。對于非圖形化或不帶瀏覽器的服務(wù)器非常有用。
五、生產(chǎn)環(huán)境使用示例
生產(chǎn)環(huán)境系統(tǒng)版本為 CentOS 7.9.2009 (Core),內(nèi)核為 5.15.81,使用 4 核 4G 的容器運行DB-GPT controller 子系統(tǒng)。
1. 使用步驟
(1)執(zhí)行腳本:/usr/local/bin/python3.10 -m cProfile -o out.prof /usr/local/bin/dbgpt start controller &
,在 Python 應(yīng)用啟動時加載 cProfile 模塊。
(2)執(zhí)行相關(guān)接口壓測。
(3)正常停止應(yīng)用,生成性能分析結(jié)果文件(out.prof)。注意:性能分析結(jié)果只能是在程序正常停止后才能輸出。常規(guī)兩種做法:其一、后臺守護進程,可以使用 kill -2 {應(yīng)用 PID}
;其二、前臺進程,通過 Ctrl + C 退出。
(4)使用snakeviz -H 0.0.0.0 -s out.prof
分析結(jié)果文件(其中 -s 僅在服務(wù)端模式下運行,不會嘗試打開服務(wù)器瀏覽器,一般情況下服務(wù)器不自帶瀏覽器;-H 0.0.0.0,支持監(jiān)聽網(wǎng)卡所有接口),執(zhí)行成功后,會輸出可訪問的 URL 地址,通過外部或本地瀏覽器打開。
2. 結(jié)果分析
使用外部或本地瀏覽器訪問 snakeviz 生成的 URL 地址。結(jié)果如下:
結(jié)果說明:
(1)結(jié)果包含兩部分,即上圖和下表。上圖展示選中方法及其子方法的調(diào)用關(guān)系、耗時及占比;下表展示所有方法及其總調(diào)用次數(shù)(ncalls)、方法本身總耗時(tottime)、方法本身平均耗時(percall)、方法及其子方法總耗時(cumtime)、方法及其子方法平均耗時(percall)以及方法所在文件位置及其行列號。
使用說明:
(1)表格任意列支持升降序操作,選中任意行,頁面上方的圖形會自動展示該方法及其子方法的調(diào)用關(guān)系、耗時及占比。
(2)單擊圖形中的任意子模塊,可查看子模塊所在方法及其子方法的調(diào)用關(guān)系、耗時及占比。
分析建議:
(1)選擇 cumtime 列降序,選擇入口代碼,逐步細看,分析瓶頸點。
(2)使用 Sunburst 圖樣展示,更易體現(xiàn)各方法耗時占比。
3. 評估加載 cProfile 對性能的影響
我們用 Jmeter 對未加載以及加載 cProfile 模塊的 Python 應(yīng)用性能進行評估,以判斷生產(chǎn)環(huán)境加載 cProfile 對性能的影響程度。結(jié)果如下:
配置 | Jmeter 壓測線程數(shù) | CPU 使用率 | 吞吐量 | 平均響應(yīng)時間 |
---|---|---|---|---|
CASE1 某應(yīng)用未加載 cProfile | 20 | 接近單核 100% | 527 | 36ms |
CASE2 某應(yīng)用加載 cProfile 后 | 20 | 接近單核 100% | 395 | 49ms |
從上表可知,加載 cProfile 后,應(yīng)用吞吐量下降 25%,平均響應(yīng)時間增加 13ms,對性能有一定影響。
五、遇到問題
kill -15 {應(yīng)用 PID} 無法生成性能分析結(jié)果文件
由于 cProfile 僅支持監(jiān)聽中斷(SIGINT)信號,導(dǎo)致 kill 15 發(fā)送 SIGTERM 信號時,無法生成性能分析結(jié)果文件。
解決辦法:使用 kill -2 {應(yīng)用 PID}。
六、使用總結(jié)
(1)cProfile 可以生成詳細的性能分布和調(diào)用鏈,非常適合作為分析和定位 Python 應(yīng)用性能瓶頸的工具。
(2)由于生成性能分析結(jié)果文件需要停止應(yīng)用,且對性能損耗較大(吞吐量降低 25%),所以一般情況下不建議在生產(chǎn)環(huán)境直接使用。不過可以使用流量復(fù)制,將生成環(huán)境的流量復(fù)制到測試或預(yù)生產(chǎn)環(huán)境,這樣既能定位實際性能瓶頸,又不影響線上業(yè)務(wù)。
到此這篇關(guān)于Python使用cProfile分析和定位應(yīng)用性能瓶頸點的文章就介紹到這了,更多相關(guān)Python cProfile內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pandas中Series和DataFrame的索引實現(xiàn)
這篇文章主要介紹了Pandas中Series和DataFrame的索引實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06python3+django2開發(fā)一個簡單的人員管理系統(tǒng)過程詳解
這篇文章主要介紹了python3+django2開發(fā)一個簡單的人員管理系統(tǒng)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-07-07使用Python制作一個數(shù)據(jù)預(yù)處理小工具(多種操作一鍵完成)
這篇文章主要介紹了使用Python制作一個數(shù)據(jù)預(yù)處理小工具(多種操作一鍵完成),本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02python pip安裝包出現(xiàn):Failed building wheel for xxx錯誤的解決
今天小編就為大家分享一篇python pip安裝包出現(xiàn):Failed building wheel for xxx錯誤的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12