py-spy: 找出 Python 程式性能瓶頸

最近覺得這個套件蠻好用的
所以就整理一下做個紀錄
py-spy
py-spy 是一款用 Rust 寫的 Python Sampling Profiler,使用上完全不需要修改 Python source code,且執行時會是執行在另外的 Process 上,對於 Profiling 來說,Overhead 是很低的。目前,py-spy 支援在 Linux, OSX, Windows 和 FreeBSD 上使用,CPython 版本支援 Python2 (2.3-2.7) 和 Python3 (3.3-3.13)
Install
最簡單的方式直接用 pip
安裝就 OK 了
pip install py-spy
也可以到 Github Release 上下載編譯好的版本 Link
Feature
py-spy 一共有三個功能,接下來我們就來好好分別介紹:
- Record
- Top
- Dump
Record
Record 會記錄每個 function 所花費的時間,並製作成 flame graph,然後輸出到 svg 檔案。
py-spy record [-o <svg_file>] -- python3 <script>
py-spy record [-o <svg_file>] --pid <pid>
範例:
py-spy record -- python3 chart.py

record
Top
Top 可以看到程式在運行的過程中在甚麼地方花費比較多的時間,可以更好的找出效能瓶頸的地方。
py-spy top -- python3 <script>
py-spy top --pid <pid>
範例:
py-spy top -- python3 chart.py

top
Dump
Dump 可以看到當前程式運行的 call stack,如果程式卡住了,或是想知道當前運行的階段,都是很好用的工具。
py-spy dump --pid <pid>
範例:
python3 -m http.server &
py-spy dump --pid $!

dump
Sudo
由於 py-spy 是運行在另一個 Process 上,如果要讀取其他 Process 的記憶體需要有 root 權限,因此我們需要使用 root 權限運行,如果不使用 root 權限的話會出現下面的錯誤:
Permission Denied: Try running again with elevated permissions by going 'sudo env "PATH=$PATH" !!'
如果單純加上 sudo
運行,則會找不到 py-spy:
sudo: py-spy: command not found
因為為了安全因素,sudo
並不會直接讀取目前使用者的 PATH
環境變數,自然找不到 py-spy,且 sudo -E
也並不會讀取 PATH
和 PYTHONPATH
,所以也不能用,最終的解法就是如訊息所示,前面加上:
sudo env "PATH=$PATH"
例如:
sudo env "PATH=$PATH" py-spy dump --pid 1111
!!
在 bash 中代表上次執行的指令如果說你用到的 Python 套件是安裝在使用者的 home,那要另外設定 PYTHONPATH
,不然 root 會找不到套件
sudo env "PATH=$PATH" "PYTHONPATH=<path>"
例如:
sudo env "PATH=$PATH" "PYTHONPATH=/home/ubuntu/.local/lib/python3.10/site-packages" py-spy top --pid 1111
Reference
- https://github.com/benfred/py-spy
- https://stackoverflow.com/questions/8633461/how-to-keep-environment-variables-when-using-sudo
- https://stackoverflow.com/questions/76964659/bash-command-not-found-even-though-its-added-to-path
如果你覺得這篇文章有用 可以考慮贊助飲料給大貓咪