Python-3.12 性能分析特性
背景
前面我们说到 Python 之父结束了自己的退休生活,出山着手解决 Python 解释器的性能问题。并于 2022-10-24 发布了 Python-3.11 版本,综合性能提升了 22%。
作为一个性能工程师 + Python 深度使用者,一发布我就去看了 3.11 版本的优化列表,有失望,有惊喜,有疑惑。
失望是因为像 GIL锁,JIT 这些都不是新版本的优化项;惊喜是因为前面几个重点问题都没有解决的情况上性能就提升了 22%,那解决了还了得;疑惑是不知道官方是怎定位性能问题的,毕竟他列出的那些优化项都不容易发现。
疑惑
为了说清楚 Python 性能优化上,怎么找热点的疑惑,我们可以看一下 Java 这门语言。Java 的性能分析工具链非常的健全,比如通过 async-profiler 这个工具我可以清楚的知道某个特定函数占用的时间,占程序总时间的百分比是多少。直观上来看就是火焰图中,哪个函数,躺的越平,躺的越宽,它的问题就越是大。
上面是一个通过 async-profiler 打出的火焰图,通过这个开发者可以清楚的看到哪个函数占用的时间多,进而有针对性地优化。
还是说回 Python,完善的性能分析工具链,有助于工程师发现问题。然而 Python 在这个方面表现要差不少,比如说火焰图中看不到 Python 代码,只能看到解释器的 C 代码;也就是没有办法直接观测到应用层的热点代码。
成熟的人要学会自己与自己和解
以 Java 做参考,确实能发现 Python 的不足。 记得有一天在公司食堂吃饭,排队时我突然就悟了;之前做 MySQL DBA 的经历告诉我,虽然我打 MySQL 的火焰图也看不到 MySQL 执行的 SQL 语句;也是只能看到 C/C++ 的函数堆栈,但这并不影响我解决问题。
是不是说只要工夫深,光是看到 C/C++ 的函数堆栈也能向上推算 SQL 语句或 Python 代码呢?看来还是人外有人啊。
Python-3.12 开始补齐短板
好不容易,11 月自己和自己和解了,官方 12 月就出了一个新功能,现在我们能在火焰图中看到 Python 代码的函数堆栈了。
具体来说就是 Python-3.12 加上了 《Python support for the Linux perf profiler》这个新特性。所有特性都在其出生时就标好了价格,这个特性的价格是,我们要在编译安装解释器的时候显示的指定开启这个功能。编译安装时的语句如下
./configure --prefix=/usr/local/python-3.12 CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
&& make -j 2
&& make instal
其中 CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" 参数就是用来开启这个功能的。
体验新特性
第一步就是构造出一个用肉眼就能看出热点的代码。
#!/usr/bin/env python3
# -*- coding: utf8 -*-
def foo():
i = 0
for j in range(100):
i = j + 100
def bar():
i = 0
for j in range(200):
i = j + 100
def main():
for i in range(100000):
foo()
bar()
if __name__ == "__main__":
main()
在这个例子中 foo 函数和 bar 函数是同构的,唯一不同的是 bar 的运行量是 foo 的一 200% ;main 函数又分别调用了他们 10w 次。
就上面的代码而言不用什么性能分析工具,直接上肉眼就能发现问题;但是线上一些机器学习的程序动不动就是 100w 行代码起步,用肉眼是看不过来的。
虽说这次的代码量只能说是一只麻雀,但不妨碍我们以鲲鹏视之,下面简单的走一下性能分析的流程。
# 执行程序并采样
perf record -F 9999 -g -o perf.data /usr/local/python-3.12/bin/python3 main.py
# 用采集到的数据画图
perf script | /usr/local/FlameGraph/stackcollapse-perf.pl > out.perf-folded
/usr/local/FlameGraph/flamegraph.pl out.perf-folded > perf.svg
最终的输出是一个 svg 图片,在浏览器里面可以直接打开,整体上看如下。
1、main 函数的耗时占总时间的 98.54%
2、foo 函数耗时占总时间的 31.02%
3、bar 函数耗时占总时间的 65.55%
现在我们能在火焰图上直观地看到,哪个函数耗时高。想像一下反正是看图,就算是面对大项目,代码根本看不过来,发现热点也应该不是什么大问题。
最后
可能是因为还是测试版本吧,现在看到的火焰图还不是特别干净,希望后面的版本能去掉其它无关信息。
相关文章
- 一个简单的Python暴力激活成功教程网站登录密码脚本「建议收藏」
- python实现矩阵的转置_Python实现矩阵转置的方法分析
- 用Python做图像处理[通俗易懂]
- 【开源分享】教你如何在HTML中执行Python脚本代码!超级简单赶紧收藏。
- python在线代码编辑器-5种最佳Python IDE和代码编辑器
- 【说站】python冒泡排序算法的性能探究
- 【说站】python选择排序算法的性能分析
- python udp编程_Python核心编程
- python冒泡排序代码通俗理解_单片机冒泡排序实验报告
- Python绘制旭日图_python绘制散点图
- Python 实现子域名查询与爆破
- Python基础语法-基本数据类型-集合
- Python format()格式化输出方法详解
- Python ftp client 处理含有中文的文件名详解编程语言
- 小白的Python之路 day5 python模块详解及import本质编程语言
- Python学习:6.python内置函数详解编程语言
- python数据类型及其特有方法详解编程语言
- python用Redis与Python实现大数据收集与分析(redis 联合)
- python编程-将Python程序转化为可执行程序[整理]
- Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
- python基础教程之对象和类的实际运用