Python:Tprof,目标分析器
Source: Hacker News
Python:引入 tprof,一款针对性分析器
分析器用于测量整个程序的性能,以找出大部分时间花费的地方。但一旦找到了目标函数,重新对整个程序进行分析以查看你的改动是否有效会既慢又繁琐。分析器会给执行带来额外开销,而且你还得从报告中挑出关心的那个函数的统计数据。我在优化客户端或开源项目时经常会经历这种循环,例如在我优化 Django 的系统检查框架时(前文)。
这种痛点促使我创建了 tprof,一款针对 Python 3.12+ 的定位分析器,只测量在指定目标函数中消耗的时间。使用它可以在优化前后测量程序,快速在命令行得到报告,看看是否产生了差异。
例如,假设你发现创建 pathlib.Path 对象是代码的瓶颈。你可以这样运行 tprof:

带比较模式的基准测试
有时在优化代码时,你想比较多个函数,例如“优化前”和“优化后”的版本。tprof 的比较模式可以实现这一点,它会在报告中添加一个 “delta” 列,显示每个函数相对于基准的快慢程度。
def before():
total = 0
for i in range(100_000):
total += i
return total
def after():
return sum(range(100_000))
for _ in range(100):
before()
after()
…你可以这样运行 tprof 来比较这两个函数:
$ tprof -x -t before -t after -m example
🎯 tprof results:
function calls total mean ± σ min … max delta
example:before() 100 227ms 2ms ± 34μs 2ms … 2ms -
example:after() 100 86ms 856μs ± 15μs 835μs … 910μs -62.27%
输出表明 after() 在此案例中大约快了 60 %。
Python API
tprof 还提供了通过上下文管理器 / 装饰器 tprof() 的 Python API。使用它可以在特定代码块中分析函数。
from tprof import tprof
def before():
total = 0
for i in range(100_000):
total += i
return total
def after():
return sum(range(100_000))
with tprof(before, after, compare=True):
for _ in range(100):
before()
after()
运行脚本会产生类似以下的输出:
$ python example.py
🎯 tprof results:
function calls total mean ± σ min … max delta
__main__:before() 100 227ms 2ms ± 83μs 2ms … 3ms -
__main__:after() 100 85ms 853μs ± 22μs 835μs … 1ms -62.35%
工作原理
tprof 使用 Python 的 sys.monitoring,这是在 Python 3.12 中引入的用于在函数或代码行执行时触发事件的新 API。sys.monitoring 让 tprof 能仅为特定目标函数注册回调,从而对程序的其余部分不产生额外开销。计时在 C 语言层面完成,以进一步降低开销。
感谢 Mark Shannon 为 CPython 贡献了 sys.monitoring!这是我第二次使用它——第一次是用于追踪意外的变更(见前文)。
结语
如果 tprof 对你有帮助,请尝试一下并告诉我你的感受!使用你喜欢的包管理器从 PyPI 安装 tprof。
—Adam