AWS Community Day Hong Kong 2025 Recap
利用另一类遥测数据,借助 AI 智能体更快改进——Yoshi Yamaguchi
Speaker:
Session: 07
Recap Series
性能剖析简介
- 性能分析器的定义:性能分析器是一种遥测工具,可以提供系统运行性能以及系统资源消耗情况的信息。
- 性能剖析的目的:性能剖析有助于调查程序的资源消耗,并提供一段时间内特定资源使用情况的统计信息。
- 与追踪的区别:追踪以时间序列方式记录资源消耗,而性能剖析提供特定时间段内的统计信息。
- 常用的性能剖析工具:
- Java:Java Flight Recorder(JFR)
- Python:cProfile(标准库)和 line_profiler(第三方工具)
- Linux:适用于任意可执行文件的 perf 命令
性能剖析在性能问题调查中的重要性
- 练习场景:假设一个 Web 应用出现延迟问题,客户端向 Web 服务器发出的请求响应缓慢。
- 目标:找出性能问题的原因并加以修复。
- 可观测性:可观测性通常与日志、指标和追踪相关,而性能剖析能够提供解决性能问题可能需要的额外洞察。
日志、指标和分布式追踪的局限性
- [ 1 ] 指标:
- 定义:指标是最常见的遥测数据类型,可以提供 CPU 使用率、内存使用率等信息。
- 局限性:指标追踪的是实例或服务的整体资源消耗(例如运行 Web 服务器的容器),无法说明应用程序中究竟是哪个具体函数或实现消耗了资源。例如,指标可以显示 Web 服务器占用了大量 CPU,却无法确定是哪个函数导致 CPU 使用率过高。
- [ 2 ] 分布式追踪:
- 定义:分布式追踪可以提供有关系统内部延迟问题的重要信息。
- 局限性:常见的分布式追踪方案需要对系统或程序进行插桩。如果某个函数未插桩,就无法获得该函数的延迟信息。为每个函数插桩不仅耗时,还可能引入性能问题。
- [ 3 ] 日志:
- 定义:日志提供特定函数在特定时间执行特定操作的信息。
- 局限性:日志只会显示处理成功或错误消息。如果函数正确处理了请求,日志只会显示成功消息,不会指出任何延迟问题。除非发生错误,否则日志无法提供延迟问题成因的信息。
结论
- 问题:日志、指标和分布式追踪虽然有用,却无法完整说明延迟问题的原因。要深入了解资源消耗并识别性能瓶颈,就必须进行性能剖析。
当前状态与理想状态总结
- [ 1 ] 目标:
- 使用可观测性的目标是找出性能问题的原因并加以修复。
- [ 2 ] 当前状态:
- 遥测数据缺口:系统存在延迟问题,CPU 或内存使用量出现激增,分布式追踪显示延迟发生变化,而日志又显示函数正常处理了请求,但仍然无法确定延迟问题的确切原因。
- [ 3 ] 理想状态:
- 精确定位:理想状态是能够找出导致性能问题的确切代码行,从而进行精准修复。
可观测性的定义
- 控制理论中的可观测性:可观测性用于衡量能在多大程度上根据系统的外部输出(遥测数据)推断其内部状态。
- 理想的可观测性:可观测性的理想状态是仅通过遥测数据就能确定问题的确切原因。
性能剖析的作用
- 填补缺口:性能剖析能够填补日志、指标和追踪无法覆盖的信息缺口。
- 最后一公里信息:要从日志、指标和追踪提供的数据进一步找到性能问题的确切原因,性能剖析可以提供最后一块关键信息。
性能剖析的传统用法
- 插桩:要使用性能剖析,需要对程序进行插桩以收集遥测数据。
- 分析:分析收集到的遥测数据,找出并修复性能问题。
为程序插桩以进行性能剖析
Go
- 标准包:使用 Go 自带的 pprof 包。
- 步骤:
- 导入 pprof 包。
- 创建性能分析器实例。
- 启动性能分析器。
- 定义停止性能剖析测量的位置。
Python
- 逐行性能分析器:使用 line_profiler 包。
- 步骤:
- 导入 line_profiler 包。
- 启用性能分析器。
- 编写需要进行性能剖析的具体处理逻辑。
- 禁用性能分析器。
面向常驻系统的持续性能剖析
- [ 1 ] 区别:
- 单次性能分析器:测量单次运行所需的时间(启动和停止计时器)。
- 持续性能分析器:按设定间隔定期采集性能剖析数据(例如每 10 秒采集一次,持续 5 分钟),并将其存储到外部(例如 Amazon S3)。
- [ 2 ] 使用场景:
- 非常适合守护进程或 Web 服务器等常驻系统,尤其适用于流量激增期间。
- [ 3 ] 解决方案:
- AWS:使用 Amazon CodeGuru,或将 Amazon Managed Grafana 与 Pyroscope 结合使用。
- 开源方案:Pyroscope,现已成为 Grafana 解决方案的一部分。
性能剖析数据分析
- 截图示例:安装了 Pyroscope 插件的 Amazon Managed Grafana,展示每个调用栈的资源使用统计。
- 下一步:数据收集完成后,进入分析阶段,找出并修复性能问题。
使用火焰图可视化性能剖析数据
- 火焰图:一种广为人知的性能剖析数据可视化方式。
- 挑战:要读懂火焰图,需要了解源代码、可视化图形的含义以及计算机科学基础概念。
解读火焰图
- [ 1 ] 示例图:
- 将整个程序调用栈的 CPU 使用情况可视化。
- [ 2 ] 解读:
- 长条:表示资源消耗较高。
- sys.call.read:执行读取操作的系统调用,消耗了大量 CPU。
- os.file.read:用于读取物理文件的 Go 标准库函数,通常实现良好且性能出色。
- [ 3 ] 结论:问题可能出在自定义函数(模拟 GNU Cut 命令的 Cut 函数)调用 os.file.read 的方式效率低下。
函数实现示例
- cut 函数:模拟 GNU Cut 命令行为的函数。
- 下一步:检查 Cut 函数的实现,找出其调用 os.file.read 时可能存在的低效之处。
演示
文件读取效率低下
- 已发现的问题:程序逐字节读取文件,效率很低,因为每读取一个字节都会触发一次系统调用。
- 知识要求:要理解这种方式效率低下的原因,需要掌握用户空间、内核空间以及计算机科学原理方面的知识。
AI 助手在性能剖析中的作用
- AI 辅助:AI 助手,尤其是大语言模型(LLM),可以帮助解读性能剖析数据。
- 更适合运维:与开发相比,LLM 更适合运维工作,因为运维的输出规模较小、确定性更高(例如识别问题),并且拥有丰富的上下文(系统规格、遥测数据和日志)。
- 开发与运维:开发工作需要生成大量源代码,输出具有不确定性,因此不太适合 LLM。
利用 AI 助手分析性能剖析数据
- 演示:一名 AWS 员工使用 AI 助手分析性能剖析数据和源代码,以找出性能问题。
- 流程:
- [ 1 ] 请 AI 助手分析性能剖析数据和源代码。
- [ 2 ] 助手判断需要使用工具将性能剖析数据可视化。
- [ 3 ] 获得批准后,助手将各函数的 CPU 使用情况可视化,并确定导致问题的具体函数。
- [ 4 ] 助手提供逐行的 CPU 使用情况,并给出改进建议。
总结
- 性能剖析数据:将性能问题与实际代码改进联系起来的关键。
- 传统分析:需要深厚的系统和计算机科学知识。
- AI 辅助:利用性能剖析数据帮助用户了解其使用方法,并加快开发进程。