对您的Python代码进行代码剖析至关重要,这一点非常重要,但在AWS Lambda中运行它会使其复杂化,因为您无法控制执行,文件系统为只读,并且在函数执行后底层计算资源会被销毁。
在这份指南中,我将带你一步步使用内置的 cProfile
模块的简单有效方式,结合上下文管理器使用,以便将性能分析数据上传到 S3 存储桶。
最后,我会教你如何生成一个自定义的调用图,从而更好地了解你应用的性能。
这张图片是通过必应搜索生成的。
介绍cProfile
cProfile
是一个强大的性能分析器,Python 自带的。你也可以直接在命令行里用它。
运行命令以生成性能分析文件:python -m cProfile -o output.pstats path/to/your/script.py
让我们用上下文管理器让性能分析变得更方便。
import cProfile
import pstats
from contextlib import contextmanager
@contextmanager
def profiler():
# 创建一个性能分析器
pr = cProfile.Profile()
pr.enable()
try:
yield
finally:
pr.disable()
# 输出性能统计数据
pr.print_stats()
with profiler():
# 这里是你的函数代码
my_function()
``
# 在 Lambda 中进行分析
我想登录CloudWatch,所以我需要更加努力地将CloudWatch与我们现有的日志记录系统集成在一起。
import cProfile
import pstats
import io
from contextlib import contextmanager
@contextmanager
def profiler(name, log):
pr = cProfile.Profile()
pr.enable()
try:
yield
finally:
pr.disable()
# 创建并记录下性能统计信息
pr.create_stats()
stats = pstats.Stats(pr)
with io.StringIO() as stream:
stats.stream = stream
stats.print_stats(100) # 限制输出为100行
log.info("性能分析: %s, \n%s", name, stream.getvalue())
with profiler("my_function", logger):
my_function() # 请在此处添加您的函数代码
注意,我仅修改了性能分析器代码,保持[单一职责原则]。
现在你的日志会显示类似这样的信息:
![](https://imgapi.imooc.com/6722dc1d093c4e3309700307.jpg)
示例来自下面的链接:<https://docs.python.org/3/library/profile.html>
我想获取原始的分析数据,以便绘制图表并执行不同的排序和操作,该如何从Lambda函数中获取它?
在我能把 profiling 数据上传到S3之前,我需要创建一个新的桶,并确保我们Lambda函数相关的IAM角色有访问该桶的必要权限。
# 创建一个S3桶实例
1. 在 AWS S3 控制台中创建一个桶
2. 确保存储桶策略允许lambda函数访问和操作:
{
"Version": "2012-10",
"Statement": [
{
"Effect": "允许访问",
"Principal": {
"AWS": "arn:aws:iam::<account_id>:role/<lambda_role>"
},
"Action": [
"s3:上传对象",
"s3:获取对象",
"s3:列出存储桶"
],
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
}
]
}
1. 将一个策略附加到 Lambda 角色上,以授予访问 S3 存储桶所需的权限。
{
"Version": "2012-10",
"Statement": [
{
"Effect": "允许效果",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
}
]
}
# 将性能分析器输出保存为文件
AWS Lambda 环境的文件系统是只读的,但允许我们在 /tmp 路径下创建文件:
import cProfile
import pstats
import boto3
@contextmanager
def profiler(name, log):
pr = cProfile.Profile()
pr.enable()
try:
yield
finally:
pr.disable()
pr.dump_stats('/tmp/output.pstats')
boto3.client('s3').upload_file('/tmp/output.pstats', 'your-bucket-name', f'{name}-output.pstats')
这时候我把文件下载到本地电脑,这样我可以调整图表参数,现在来看看效果。
![](https://imgapi.imooc.com/6722dc1e090dd01311740703.jpg)
来自<https://github.com/jrfonseca/gprof2dot>的输出示例
# 生成调用关系图
为了生成一张可视化图表,我们将使用这个很棒的工具包[gprof2dot](https://github.com/jrfonseca/gprof2dot),
apt-get install python3 graphviz # 安装Python3和graphviz
pip install gprof2dot # 安装gprof2dot
一旦你安装了 `gprof2dot`,你就可以用以下命令来生成调用图:
<具体命令>
注意: 请根据实际情况填写具体的命令。
gprof2dot -f pstats my_function-output.pstats | dot -Tpng -o output.png
这条命令会从S3桶中读取性能数据,生成DOT图表,然后将其渲染成PNG图片文件。
经过几次尝试后,我发现了一个更加详细的指令。
gprof2dot -n 5 -e 4 --node-label=self-time --node-label=total-time --total=callstacks -f pstats s3://你的桶名/my_function-output.pstats | dot -Tpng -o output_less.png
这行命令用于生成一个可视化图,展示函数调用栈的性能分析结果。这里your-bucket-name
是你的实际桶名。
这些选项用于自定义输出,包括节点标签和统计信息。
输出文件名为output_less.png
。
此命令会去掉一些耗时较短的节点和边,并用自身时间和总时间信息来标记节点,而不是使用默认的百分比形式显示。
![](https://imgapi.imooc.com/6722dc2009a59c9f04880221.jpg)
来自<https://github.com/jrfonseca/gprof2dot>的输出示例
这种方法既简单又有效,将帮助你在 AWS Lambda 中分析你的 Python 代码的性能,从而开始优化应用性能,使你的应用表现更佳。
现在真正的挑战开始了——分析性能剖析数据并解读分析结果以识别性能瓶颈点。祝你好运哦!
共同学习,写下你的评论
评论加载中...
作者其他优质文章