使用 cProfile 分析和定位 Python 应用性能瓶颈

picture.image

向AI转型的程序员都关注公众号 机器学习AI算法工程

一、背景需求

性能压测时,发现某接口存在性能瓶颈,期望借助工具定位该瓶颈,最好能定位至具体慢方法。

二、cProfile 简介

cProfile 是 Python 标准库中的一个模块,用于对 Python 程序进行性能分析,它能输出每个函数的调用次数、执行耗时等详细信息,可帮助开发者识别程序中运行缓慢的方法,以便进行性能优化,适合作为上述需求的解决方案。

此外,Python 还内置了使用纯 Python 实现的 profile 模块,与 cProfile 功能一样,只不过 cProfile 是用 C 语言编写,性能更高、开销更小,适合在性能敏感的环境(如线上生产环境)中使用。profile 是纯 Python 实现的模块,性能开销相对较大,但因其用 Python 编写,易于理解和修改,适合学习时使用。

三、使用方法

cProfile 支持三种使用方法,一是硬编码于代码中;二是在 Python 应用启动时加载 cProfile 模块;三是通过 IDE(PyCharm)运行。开发环境建议采用方法三,因其简单易用且结果图表丰富;生产环境建议采用方法二,此方法对代码无侵入性。

1. 硬编码于代码中

示例代码:


        
import cProfile  
  
def my\_function():  
    # Some code to profile  
    pass  
  
profiler = cProfile.Profile()  
profiler.enable()  
my_function()  
profiler.disable()  
profiler.print_stats()  

    

执行结果:


        
2 function calls in 0.000 seconds  
  
Ordered by: standard name  
  
ncalls  tottime  percall  cumtime  percall filename:lineno(function)  
    1    0.000    0.000    0.000    0.000 test.py:3(my_function)  
    1    0.000    0.000    0.000    0.000 {method 'disable' of '\_lsprof.Profiler' objects}  

    

结果字段说明:

ncalls:函数调用的次数。

tottime:在该函数中花费的总时间,不包括调用子函数的时间。

percall:tottime 除以 ncalls。

cumtime:该函数及其所有子函数中花费的总时间。

percall:cumtime 除以原始调用次数。

filename:lineno(function):函数所在的文件名、行号和函数名。

2. 在 Python 应用启动时加载 cProfile 模块

示例代码:


        
python -m cProfile my_script.py # 方法一、将结果输出至控制台  
python -m cProfile -o output.prof my_script.py # 方法二、将结果保存到指定的prof文件  

    

可使用 snakeviz 插件(安装方法为pip install snakeviz)分析 prof 文件。执行snakeviz output.prof后,会将结果挂载到 web 容器中,支持通过 URL(如http://127.0.0.1:8080/snakeviz/xxxoutput.prof)访问。

3. 通过 IDE(PyCharm)运行

使用方法:

通过菜单 [run] > [profile 'app'](其中 app 为应用名称,下同)启动应用。待应用执行完毕且停止后,相关面板会输出相应的调用统计与调用链。

调用统计:

picture.image

表头“Name”表示被调用的模块或函数;“Call Count”表示被调用次数;“Time (ms)”表示耗时及百分比,时间单位为毫秒。

点击表头列名可对该列进行排序。

在调用统计中,选择“name”列的单元格,右键选中“Navigate to Source”或“Show on Call Graph”,可打开其源码或对应的调用链及位置。

调用链:

picture.image

此外,通过菜单 [run] > [Concurrency Diagram 'app'] 启动程序,可查看到线程和异步协程(Asyncio)的调用情况,如下图所示:

picture.image

四、相关配置项

1. cProfile


        
[root@test bin]# python3 -m cProfile -h  
Usage: cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ...  
  
Options:  
  -h, --help            show this help message and exit  
  -o OUTFILE, --outfile=OUTFILE  
                        Save stats to <outfile> # 将分析结果输出到指定的文件中。  
  -s SORT, --sort=SORT  Sort order when printing to stdout, based on pstats.Stats class # 指定输出结果的排序方式。可以根据不同的字段进行排序,如 time, cumulative, calls 等。  
  -m                    Profile a library module # 分析一个模块,而不是一个脚本文件  

    

2. snakeviz


        
[root@test bin]# snakeviz --help  
usage: snakeviz [-h] [-v] [-H ADDR] [-p PORT] [-b BROWSER_PATH] [-s] filename  
  
Start SnakeViz to view a Python profile.  
  
positional arguments:  
  filename              Python profile to view  
  
options:  
  -h, --help            show this help message and exit  
  -v, --version         show program \`s version number and exit  
  -H ADDR, --hostname ADDR hostname to bind to (default: 127.0.0.1) # 用于指定绑定的主机名,默认值为 127.0.0.1,即本地主机。  
  -p PORT, --port PORT  port to bind to; if this port is already in use a free port will be selected automatically (default: 8080) # 用于指定绑定的端口。如果指定的端口已被占用,程序将自动选择一个空闲端口。默认值为 8080。  
  -b BROWSER_PATH, --browser BROWSER_PATH  name of webbrowser to launch as described in the documentation of Python\'s webbrowser module: https://docs.python.org/3/library/webbrowser.html # 按照 Python 的 webbrowser 模块的文档描述,指定要启动的浏览器名称。用户可以通过指定浏览器的路径来控制使用哪个浏览器打开应用。  
 -s, --server start SnakeViz in server-only mode--no attempt will be made to open a browser # 仅在服务器模式下启动 SnakeViz,不会尝试打开服务器中的浏览器。对于非图形化或不带浏览器的服务器非常有用。  

    

五、生产环境使用示例

生产环境系统版本为 CentOS 7.9.2009 (Core),内核为 5.15.81,使用 4 核 4G 的容器运行DB-GPT controller 子系统。

1. 使用步骤

(1)执行脚本:/usr/local/bin/python3.10 -m cProfile -o out.prof /usr/local/bin/dbgpt start controller &,在 Python 应用启动时加载 cProfile 模块。

(2)执行相关接口压测。

(3)正常停止应用,生成性能分析结果文件(out.prof)。 注意: 性能分析结果只能是在程序正常停止后才能输出。常规两种做法:其一、后台守护进程,可以使用 kill -2 {应用 PID};其二、前台进程,通过 Ctrl + C 退出。

(4)使用snakeviz -H 0.0.0.0 -s out.prof分析结果文件(其中 -s 仅在服务端模式下运行,不会尝试打开服务器浏览器,一般情况下服务器不自带浏览器;-H 0.0.0.0,支持监听网卡所有接口),执行成功后,会输出可访问的 URL 地址,通过外部或本地浏览器打开。

2. 结果分析

使用外部或本地浏览器访问 snakeviz 生成的 URL 地址。结果如下:

picture.image

结果说明:

(1)结果包含两部分,即上图和下表。上图展示选中方法及其子方法的调用关系、耗时及占比;下表展示所有方法及其总调用次数(ncalls)、方法本身总耗时(tottime)、方法本身平均耗时(percall)、方法及其子方法总耗时(cumtime)、方法及其子方法平均耗时(percall)以及方法所在文件位置及其行列号。

使用说明:

(1)表格任意列支持升降序操作,选中任意行,页面上方的图形会自动展示该方法及其子方法的调用关系、耗时及占比。

(2)单击图形中的任意子模块,可查看子模块所在方法及其子方法的调用关系、耗时及占比。

分析建议:

(1)选择 cumtime 列降序,选择入口代码,逐步细看,分析瓶颈点。

(2)使用 Sunburst 图样展示,更易体现各方法耗时占比。

3. 评估加载 cProfile 对性能的影响

我们用 Jmeter 对未加载以及加载 cProfile 模块的 Python 应用性能进行评估,以判断生产环境加载 cProfile 对性能的影响程度。结果如下:

配置Jmeter 压测线程数CPU 使用率吞吐量平均响应时间
CASE1 某应用未加载 cProfile20接近单核 100%52736ms
CASE2 某应用加载 cProfile 后20接近单核 100%39549ms

从上表可知,加载 cProfile 后,应用吞吐量下降 25%,平均响应时间增加 13ms,对性能有一定影响。

五、遇到问题

1. kill -15 {应用 PID} 无法生成性能分析结果文件

由于 cProfile 仅支持监听中断(SIGINT)信号,导致 kill 15 发送 SIGTERM 信号时,无法生成性能分析结果文件。

解决办法:使用 kill -2 {应用 PID}。

六、使用总结

(1)cProfile 可以生成详细的性能分布和调用链,非常适合作为分析和定位 Python 应用性能瓶颈的工具。

(2)由于生成性能分析结果文件需要停止应用,且对性能损耗较大(吞吐量降低 25%),所以一般情况下不建议在生产环境直接使用。不过可以使用流量复制,将生成环境的流量复制到测试或预生产环境,这样既能定位实际性能瓶颈,又不影响线上业务。

机器学习算法AI大数据技术

搜索公众号添加: datanlp

picture.image

长按图片,识别二维码

阅读过本文的人还看了以下文章:

实时语义分割ENet算法,提取书本/票据边缘

整理开源的中文大语言模型,以规模较小、可私有化部署、训练成本较低的模型为主

《大语言模型》PDF下载

动手学深度学习-(李沐)PyTorch版本

YOLOv9电动车头盔佩戴检测,详细讲解模型训练

TensorFlow 2.0深度学习案例实战

基于40万表格数据集TableBank,用MaskRCNN做表格检测

《基于深度学习的自然语言处理》中/英PDF

Deep Learning 中文版初版-周志华团队

【全套视频课】最全的目标检测算法系列讲解,通俗易懂!

《美团机器学习实践》_美团算法团队.pdf

《深度学习入门:基于Python的理论与实现》高清中文PDF+源码

《深度学习:基于Keras的Python实践》PDF和代码

特征提取与图像处理(第二版).pdf

python就业班学习视频,从入门到实战项目

2019最新《PyTorch自然语言处理》英、中文版PDF+源码

《21个项目玩转深度学习:基于TensorFlow的实践详解》完整版PDF+附书代码

《深度学习之pytorch》pdf+附书源码

PyTorch深度学习快速实战入门《pytorch-handbook》

【下载】豆瓣评分8.1,《机器学习实战:基于Scikit-Learn和TensorFlow》

《Python数据分析与挖掘实战》PDF+完整源码

汽车行业完整知识图谱项目实战视频(全23课)

李沐大神开源《动手学深度学习》,加州伯克利深度学习(2019春)教材

笔记、代码清晰易懂!李航《统计学习方法》最新资源全套!

《神经网络与深度学习》最新2018版中英PDF+源码

将机器学习模型部署为REST API

FashionAI服装属性标签图像识别Top1-5方案分享

重要开源!CNN-RNN-CTC 实现手写汉字识别

yolo3 检测出图像中的不规则汉字

同样是机器学习算法工程师,你的面试为什么过不了?

前海征信大数据算法:风险概率预测

【Keras】完整实现‘交通标志’分类、‘票据’分类两个项目,让你掌握深度学习图像分类

VGG16迁移学习,实现医学图像识别分类工程项目

特征工程(一)

特征工程(二) :文本数据的展开、过滤和分块

特征工程(三):特征缩放,从词袋到 TF-IDF

特征工程(四): 类别特征

特征工程(五): PCA 降维

特征工程(六): 非线性特征提取和模型堆叠

特征工程(七):图像特征提取和深度学习

如何利用全新的决策树集成级联结构gcForest做特征工程并打分?

Machine Learning Yearning 中文翻译稿

蚂蚁金服2018秋招-算法工程师(共四面)通过

全球AI挑战-场景分类的比赛源码(多模型融合)

斯坦福CS230官方指南:CNN、RNN及使用技巧速查(打印收藏)

python+flask搭建CNN在线识别手写中文网站

中科院Kaggle全球文本匹配竞赛华人第1名团队-深度学习与特征工程

不断更新资源

深度学习、机器学习、数据分析、python

搜索公众号添加: datayx

picture.image

0
0
0
0
评论
未登录
暂无评论