Py-Spy是Python程序的抽样分析器,可视化查看Python程序在哪些地方花了更多时间
1.安装
pip install py-spy
验证安装是否成功
py-spy -h py-spy 0.3.3 Sampling profiler for Python programs USAGE: py-spy <SUBCOMMAND> OPTIONS: -h, --help Prints help information -V, --version Prints version information SUBCOMMANDS: record Records stack trace information to a flamegraph, speedscope or raw file top Displays a top like view of functions consuming CPU dump Dumps stack traces for a target program to stdout help Prints this message or the help of the given subcommand(s)
从上面看到有三个子命令
record:生成火焰图
top:实时查看每个函数运行时间并统计
dump:显示每个python线程的当前调用堆栈
2.示例
main.py
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str price: float is_offer: bool = None @app.get("/") def home(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int, q: str = None): return {"item_id": item_id, "q": q} @app.put("/items/{item_id}") def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id}
启动
uvicorn main:app --host 0.0.0.0
(1)record
生成火焰图
py-spy record -o profile.svg --pid 11004
在Ubuntu下会出现
Permission Denied: Try running again with elevated permissions by going 'sudo env "PATH=$PATH" !!'
执行
sudo env "PATH=$PATH" py-spy record -o profile.svg --pid 11004
使用ab压力测试
ab -n 10000 -c 100 http://localhost:8000/
生成的火焰图
通过生成火焰图分析程序瓶颈,看图中最下方哪个峰顶是平的,程序的性能问题就可以从那入手去解决
(2)top
显示了在python程序中花费最多时间的功能的实时视图
py-spy top --pid 11004
说明:
参数
按%Own排序:当前在该函数中花费的时间的百分比
按%Total排序:函数及其子级中当前的时间百分比
按OwnTime排序:函数中花费的总时间
按TotalTime排序:该函数及其子项花费的总时间
通过OwnTime可以比较直接的看出程序运行中,所占比消耗时间最多的函数
https://github.com/benfred/py-spy
(3)dump
显示每个线程的调用栈
$ sudo env "PATH=$PATH" py-spy dump --pid 1615 Process 1615: /usr/bin/python /home/baby/.local/bin/uvicorn main:app --host 0.0.0.0 Python v3.7.9 (/usr/bin/python3.7) Thread 1615 (idle): "MainThread" select (selectors.py:468) _run_once (asyncio/base_events.py:1750) run_forever (asyncio/base_events.py:541) run_until_complete (asyncio/base_events.py:574) run (uvicorn/server.py:48) run (uvicorn/main.py:386) main (uvicorn/main.py:362) invoke (click/core.py:610) invoke (click/core.py:1066) main (click/core.py:782) __call__ (click/core.py:829) <module> (uvicorn:8) Thread 1624 (idle): "ThreadPoolExecutor-0_0" _worker (concurrent/futures/thread.py:78) run (threading.py:870) _bootstrap_inner (threading.py:926) _bootstrap (threading.py:890) Thread 1625 (idle): "ThreadPoolExecutor-0_1" _worker (concurrent/futures/thread.py:78) run (threading.py:870) _bootstrap_inner (threading.py:926) _bootstrap (threading.py:890) Thread 1626 (idle): "ThreadPoolExecutor-0_2" _worker (concurrent/futures/thread.py:78) run (threading.py:870) _bootstrap_inner (threading.py:926) _bootstrap (threading.py:890) Thread 1710 (idle): "ThreadPoolExecutor-0_3" _worker (concurrent/futures/thread.py:78) run (threading.py:870) _bootstrap_inner (threading.py:926) _bootstrap (threading.py:890) Thread 1711 (idle): "ThreadPoolExecutor-0_4" _worker (concurrent/futures/thread.py:78) run (threading.py:870) _bootstrap_inner (threading.py:926) _bootstrap (threading.py:890)
注:
如果在windows下,使用dump,会报错
>py-spy dump --pid 4644
Error: 函数不正确。 (os error 1)