Python性能分析利器:py-spy原理、安装与实战指南

Miles
Miles
发布时间:2026-10-14 | 3人浏览过
原创

本文详细介绍Python性能分析工具py-spy的安装与核心用法。作为基于Rust开发的低开销抽样分析器,py-spy无需修改代码即可监控生产环境。文章涵盖通过record命令生成火焰图以定位瓶颈,以及利用top命令实时查看函数耗时并排序分析,帮助开发者高效解决Python应用的性能问题。

Py-Spy简介与安装

Py-Spy简介

参考官方定义:

Py-Spy是一款针对Python程序的抽样分析器。它能够可视化展示Python程序在哪些环节消耗了更多时间,且整个监控过程无需重启程序或修改任何工程代码。由于Py-Spy由Rust编写,其运行速度与编译后的Python程序处于不同进程,因此开销极低。这意味着Py-Spy可安全地应用于生产环境中的Python应用调优分析。

GitHub仓库地址:https://github.com/benfred/py-spy

安装步骤

执行命令:pip install py-spy

安装完成后,运行py-spy -h以验证安装是否成功并查看帮助文档。

py-spy通过命令行操作,支持传入目标程序的PID或待运行的Python程序命令行。它提供三个子命令:

  • record:用于生成火焰图
  • top:实时查看各函数运行时间并进行统计
  • dump:显示每个Python线程当前的调用堆栈

生成火焰图分析性能瓶颈

利用py-spy生成火焰图

py-spy是一个易用且功能强大的库,阅读其README文档后即可上手。该工具不仅能生成Profile火焰图,还能精准定位耗时最长的代码位置。其最大优势在于完全无需修改代码,相较于其他性能调查工具,这一特性尤为突出。在调试线上正在运行的程序时,只需提供进程ID,py-spy即可直接生成火焰图。

执行命令:py-spy record -o profile.svg --pid 12345

或者

执行命令:py-spy record -o profile.svg-python myprogram.py

其中"12345"代表程序运行的PID。执行该命令后,py-spy开始对程序simple进行抽样并生成火焰图。等待约1分钟后按Ctrl+C结束,当前目录下将生成profile.svg火焰图,效果如下图所示:

火焰图的分析直观简单,主要关注“平顶”区域。若图中最下方的峰顶呈现平坦状态,则表明程序的性能问题可从该处着手解决。此处不展开火焰图的具体解读方法,如有不明之处可自行查阅相关资料。

通过生成火焰图分析程序瓶颈,大概率能发现并解决80%的性能问题。但若火焰图中没有平顶,而程序依然运行缓慢,该如何定位问题?

当无平顶时,定位程序中耗时最多的函数或代码

如下图所示,通过火焰图并未发现程序中的平顶现象。

使用Top命令实时查看函数耗时

Top功能介绍

此时需使用py-spy提供的top命令。Top功能展示了Python程序中耗时最多的函数的实时视图,类似于Unix系统中的top命令。

执行命令:py-spy top --pid 12345

或者

执行命令:py-spy top-python myprogram.py

输入上述命令后,控制台将显示程序实时的运行状态。此处介绍图中4个参数的含义,并可通过按下1、2、3、4四个按键,使程序按照下述方式进行排序。

  • 按%Own排序(当前在该函数中花费的时间百分比)
  • 按%Total排序(函数及其子级中当前的时间百分比)
  • 按OwnTime排序(函数中花费的总时间)
  • 按TotalTime排序(该函数及其子项花费的总时间)

比较直观的做法是使用选项3,可直接看出程序运行中占比消耗时间最多的函数,随后从函数角度进行分析。如下图所示,可以看出wrap装饰器函数消耗的时间最长,使用wrapt(用C编写的装饰器)进行替换后,效率有了显著提升。

​

总结:相较于其他Python性能分析工具,py-spy的优势在于使用简单,无需对代码做任何改动,且能在保护现场的情况下直接生成火焰图,同时支持查看程序实时运行状态。

火焰图解读指南

如何解读火焰图

首先需要明确以下几点:

X轴方向代表采样时间。

Y轴方向代表函数调用栈。

若提供如下所示的火焰图,应得出哪些信息:

1. a()是起始执行函数,但未消耗CPU,在该函数中调用了b()和h()。

2. a()的两个分支b()和h()表明a()内部可能存在条件语句。继续观察可见,b()分支消耗的CPU远高于h()。

3. h()函数未消耗CPU,CPU资源全被i()函数占用。

4. b()这条支路继续向上延伸至d(),由d()的子函数e()消耗部分CPU,f()下的g()消耗部分CPU。注意d()最右侧上方缺失了一块,这部分即为d()执行所消耗的CPU。

结论:

消耗CPU的函数包括e()、g()、d()和i()。

因此,若需调查性能问题,首先应调查g(),其次是i()。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表