漫画:如何分析运行中的 Python 程序?

内容简介

  • 如何使用 py-spy

  • 如何读懂火焰图

遇到的问题

大佬组长透露出几个关键信息:

  • 1. 要排查的是线上正在运行的 Python 程序

  • 2.“凌晨 3 点多的时候可能出现”,表示问题并不是每天都出现的

  • 3. 问题现象是程序卡死,重启后,有可以正常运行

线上服运行在真实环境,使用真实数据长时间运行,这种非必发性的错误通常难以在测试服或灰度服中发现,而且这种错误看日志通常难以判断出现这种问题的真正原因,可能其他地方的代码出现了问题,但没有被处理,导致异常状态一直堆积,一段时间后才出现的问题。

根据上面的关键信息,我开始进行如下思考:

  • 1. 思考是否可以构建「最小实例进行复现呢?」,可以复现就说明找到了问题。

  • 2. 是代码的问题还是其他依赖服务存在问题导致本 Python 程序出现问题?

自己在测试环境运行相同的代码,发现没有任何问题,那是其他依赖的问题?这么多依赖服务,一个个查是不现实的,那只能在代码中加多点日志,然后再放到线上去看了?

其实还有使用更简单的方法去定位错误,那就使用 py-spy

使用 py-spy

py-spy 是一款开源的 Python 程序的抽样分析工具,使用 py-spy 可以很直观的查看 Python 程序的进程堆栈以及不同方法的耗时等,整个监控方式不需要对正在运行的程序做任何处理,即你不要修改程序代码也不需要重启程序。

py-spy 使用 Rust 语言开发,Rust 语言是一门号称 C/C++ 的运行速度、类 JavaScript 写法的语言,简单而言,就是开发效率高运行效率也高。py-spy 基于 Rust 语言提供的强大特性,使得它可以安全的用于生产环境中的 python 程序。

通过 pip 安装 py-spy

pip3 install -i https://pypi.doubanio.com/simple/ py-spy

安装完后就可以使用了,如果你是 windows 用户,需要下载预构建的二进制文件进行安装,细究可参考官方说明(在最后参考一节)。

通过 py-spy help 查看该工具支持的指令,总共就 3 种不同的指令,非常简单。

首先来使用 top 命令,它会生成类似 Unix 系统中 top 命令的效果,它有两种使用方式,分别如下。

# 如果python程序正在运行,直接通过pid进行采样
sudo py-spy top --pid 12345
# OR
# 如果python程序没有运行,可以使用如下命令
sudo py-spy top -- python myprogram.py

因为线上 Python 服务本身就是运行状态,所以直接通过 pid 去查看运行进程中的信息,这些信息会依据 py-spy 的采样实时更新。

从上图可以看出,top 命令会显示出当前 Python 进程中 GIL 锁的使用率、活跃线程率、线程数等总体信息,此外还会列出程序中不同方法的占用时间,其中的信息包含了使用的第三方库所占用的时间。

此外,还可以让 py-spy 生成火焰图(flame graph),通过火焰图可以更直观的判断出程序的性能情况。

py-spy 生成火焰图只需使用 record 命令则可,与 top 命令类似,同样有两种使用方式,如下。

py-spy record -o profile.svg --pid 12345
# OR
py-spy record -o profile.svg -- python myprogram.py

-o 参数用于指定火焰图生成的路径。

如果你不清楚怎么看火焰图,不用紧张,后面会介绍火焰图的使用方法。

如果你的程序突然卡死了,你又不清楚它为何会卡死,此时就可以通过 py-spy 的 dump 命令来查看当前程序的调用堆栈,通过调用堆栈来判断 Python 程序挂在何处。

dump 命令只能用于正在运行的 Python 程序。

py-spy dump --pid 12345

从图中可以很清晰的看出当前 Python 程序中所有活跃线程的调用栈。

加多 --locals 参数可以将每个堆栈帧关联的局部变量也打印出来,如下图。

py-spy 的简单用法就介绍完了。

读懂火焰图

火焰图通常是 svg 图片,可以直接通过 Chrome 浏览器打开。

py-spy 生成的火焰图其火焰是向下的,而有些工具生成的火焰图其火焰是向上,样式不同,但没有什么本质区别。

看到刚刚 py-spy 生成的火焰图。

火焰图的 y 轴表示程序的调用栈,每一层都是一个函数,调用栈越深,火焰就越高,最底部就是当前正在执行的函数,上方都是它的父函数。

火焰图 x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,表示它被抽样程序抽到的次数越多,也就表示该方法的执行时间较长。

需要注意,火焰图 x 轴不代表时间,而是所有调用栈合并后,按字母顺序排列而成。

此外,火焰图的颜色没有特殊含义。

火焰图是可以互动的。

  • 1. 鼠标悬浮

当鼠标悬浮在火焰的某一层,火焰图都会显示出当前层对应的完整函数名、抽样抽中的次数、占据总抽样次数的百分比。

  • 2. 可点击放大查看

可以点击火焰的某一层,火焰图会水平放大,该层会占满 x 轴,从而显示出该层的详细信息。

  • 3. 可以搜索

点击火焰图中的 Search 会显示一个搜索框,用户可以输入关键字或正则表达式,所有符合条件的函数名都会高亮显示。

其实 Chromme 浏览器本身就可以生成访问某网站时的性能火焰图。

打开开发者工具 -> 切换到「Performance」 -> 点击「录制」按钮开始记录数据,此时访问 github.com,等网页完全加载后,停止录制,此时,开发者工具就会显示出一个时间轴,而它的下方就是一个火焰图。通过这个火焰图可以详细的分析当前页面的性能。

与传统的火焰图不同,x 轴是时间轴,而不是抽样次数。

参考

  • 1.py-spy github:https://github.com/benfred/py-spy

  • 2. 如何读懂火焰图?:https://www.ruanyifeng.com/blog/2017/09/flame-graph.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒编程-二两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值