利用 Amazon APerf 提升性能,从低于目标 50 到超过目标 36
作者:Macey Neff,2024 年 8 月 7 日发表于 Amazon EC2、Amazon Elastic Block Store (Amazon EBS)、最佳实践、计算 和 Graviton
文章要点
使用 Amazon APerf 工具识别和修复 AWS 实例的性能问题。透过对 Renaissance Finaglehttp 基准测试进行调整,降低性能瓶颈,进而将性能从低于目标的 50 提升至超过目标 36。系统性能调整的过程分为两个主要阶段:系统问题检查和 CPU 核心瓶颈分析。在不同系统上,软件的性能有时并不符合预期,这可能是由于配置错误、代码错误或硬体性能差异所致。Amazon APerf 是一款强大的工具,旨在帮助识别和解决 AWS 实例及其他计算机上的性能问题。APerf 同时捕捉全面的系统指标,并在互动报告中可视化这些数据。这使得用户能够分析 CPU 使用率、中断、内存使用情况及 CPU 核心性能计数器PMU等指标。尤其是,APerf 可协助比较不同实例类型间的性能,生成侧边报告,便于用户进行比较。对于需要优化应用性能的开发者、系统管理员和性能工程师来说,APerf 无疑具有很高的价值。接下来,我们将以 Renaissance 基准测试为例,展示如何使用 APerf 进行调试并找出性能瓶颈。
案例展示
我们发现 Renaissance finaglehttp 基准测试在一台 c7g16xl Graviton3 实例上的运行速度比参考实例慢了 50。这一现象令人意外,因为 Graviton3 性能应该与参考实例相当甚至更好,这对于其他基于 Java 的工作负载来说也是如此。因此,这很可能是某个配置问题。Renaissance 基准测试是用 Scala 编写的,并生成 Java 字节码,因此我们的调查将集中在 Java JVM 和系统级配置方面。
概述
系统性能调整是一个迭代过程,主要分为两个阶段:第一阶段著重于整体系统问题,第二阶段则关注 CPU 核心瓶颈。APerf 同时支援这两个阶段的协助。
APerf 能将多个实例的数据并排呈现在一份报告中,通常为参考系统与待调整系统。参考系统提供可供比较的基准值。孤立的指标评估较为困难,一个指标在一般情况下可能是可接受的,但与参考系统的比较则更容易发现改进的空间。
在第一阶段,APerf 帮助识别不寻常的系统行为,如高中断负载、过度 I/O 等待及异常的网络层模式等问题。对这些问题进行调整后,例如通过修改 JVM 标志,我们便可进入第二阶段。使用第一阶段系统调整的数据,收集和评估新的 APerf 数据,重点关注 CPU 核心性能指标。
当 SUT CPU 核心的指标与参考系统相比存在劣势时,即表示潜在的改进空间。在接下来的部分中,我们将详细讨论这两个阶段。有关系统调整的更多背景资讯,请参考 性能手册 中的 AWS Graviton 入门指南。
初始数据收集
以下是使用 APerf 收集 240 秒系统数据的示例:
bash
启用 PMU 访问
echo 0 sudo tee /proc/sys/kernel/perfeventparanoid
APerf 需要打开的档案数量超过默认限制。
ulimit n 65536
通常 APerf 会在另一个终端运行。为了演示目的,此处以后台形式发送。
/aperf record runname finagle1 period 240 amp
在 64 个 CPU 上,APerf 需要稍少于 15 秒才能报告准备好进行数据收集。
sleep 15java jar renaissancegpl0142jar r 8 finaglehttp
APerf 报告生成如下:
bash/aperf report run finagle1
然后,可以使用浏览器查看报告:
bashfirefox aperfreportfinagle1/indexhtml
APerf 报告能在同一报告中并排呈现多个数据集。
bash/aperf report run finagle1c7g run finagle1reference run
请注意,检查 APerf 中随时间变化的 CPU 使用率至关重要。一些数据可能是在系统闲置时收集的,因此在闲置期间的指标并无实质价值。
第一阶段:系统层级
在这一阶段,我们查找系统层级的差异。为此,APerf 在 c7g16xl 和参考系统运行 finaglehttp 时收集数据,而参考系统提供目标数据以供比较。任何显著的差异都值得进一步检查。
首先的差异可以在以下图中看到。
APerf 的 CPU 使用率图显示,在每次运行的开始,Graviton3红色高亮部分的下降幅度大于在参考实例上的下降幅度。
GC 运行时的日志信息暗示了可能的原因,因为它们恰好 coincide 与 CPU 使用率的下降。
bash====== finaglehttp (web) [default],第 0 次迭代开始 ======GC 在操作前:完成时间 32692 毫秒,内存使用量 87588 MB 31411 MB。====== finaglehttp (web) [default],第 0 次迭代完成6534533 毫秒 ======
JVM 骇客通常会花费相当多的时间进行垃圾回收,在此过程中它必须暂停所有线程,选择不同的 GC 可能会产生正面影响。
在 OpenJDK17 中,默认的 GC 是 G1GC。由于这些实例拥有 64 个 CPU,因此可以进行高度并行的 GC,因此使用 parallelGC 作为替代方案是可行的。Graviton 入门指南还建议在处理 Java 性能问题时检查 GC 日志。使用 JVM 的 Xloggc 选项进行交叉检查后,确定使用 parallelGC 时的 GC 时间显著下降。
第二个差异可在以下图中看到,CPU 到 CPU 的中断IPI活动在 Graviton3 上的数量超过参考系统 10 倍以上,这意味著 c7g16xl 上的 IRQ 工作需要额外花费 CPU 时间,而参考系统则不需要。
一元机场登录入口通过 grep 查询内核提交信息有助于找出修补程序,从而解决特定问题,例如 IPI 效率低下。
这个 调度修补程序使性能提高 19。另一个 IPI 修补程序 则提供了额外的 1 改进。切换到 Linux51561 使我们能够使用这些 IPI 改进。以下图示显示了 APerf 中的效果。
第二阶段:CPU 核心层级
现在系统层级问题已经解决,焦点转向 CPU 核心。APerf 收集的数据显示参考实例与 Graviton3 在 PMU 数据方面有显著差异。
PMU 指标Graviton3参考系统每千条指令的分支预测错误164每千条指令的指令转译缓存 (TLB) 错误834每时钟周期指令数0606注意:参考系统的 CPU 时钟频率比 c7g16xl 高 20。一般来说,每时钟周期指令数IPC乘以时钟频率等于 CPU 完成的工作量。
解决 CPU 核心瓶颈
PMU 指标的首次改善源自于使用 parallelGC 选项。尽管其目的是增加 CPU 使用率,但以下图显示了分支错过计数的降低。将 JIT 分级编译 限定为仅使用 C2 模式有助于通过减少分支间接性和提高已执行代码的局部性来改善分支预测。最后,添加 透明大页 帮助支援分支预测逻辑,并避免在 DDR 记忆体中进行冗长的地址翻译查找。以下图表显示所选 JVM 选项的效果。
每千条指令的分支错过c7g16xl

JVM 选项从左到右:
XXUseParallelGCXXUseParallelGC XXTieredCompilationXXUseParallelGC XXTieredCompilation XXUseTransparentHugePages使用上述选项后,APerf 显示分支预测错误率从最初的 16 降至 11。分支错误预测将产生成本高昂的性能惩罚,因为它们会导致在计算结果时浪费周期,最终需要丢弃。此外,这些错误预测会使得预取和快取子系统无法加载必要的后续指令。结果,将会出现成本高昂的 管道停顿 和 前端停顿,使 CPU 无法执行指令。
代码稀疏性
JVM 选项从左到右:
XXUseParallelGCXXUseParallelGC XXTieredCompilationXXUseParallelGC XXTieredCompilation XXUseTransparentHugePages代码稀疏性测量指令码的紧凑性及相关代码的相对位置。关闭分级编译会显示出效果。较低的稀疏性有助于提升分支预测及快取子系统的效能。
每千条指令的指令 TLB 错误c7g16xl
JVM 选项从左到右:
XXUseParallelGCXXUseParallelGC XXTieredCompilationXXUseParallelGC XXTieredCompilation XXUseTransparentHugePages指令 TLB 错误的大幅减少是由于使用透明大页所致,这增加了虚拟地址转换存在于 TLB 的可能性,因为所需的条目更少。这样可避免翻译表查询,因为否则需要遍历 DDR 记忆体中的条目,而这会消耗数百个 CPU 周期。
每时钟周期的指令数 (IPC)
JVM 选项从左到右:
XXUseParallelGCXXUseParallelGC XXTieredCompilationXXUseParallelGC XXTieredCompilation XXUseTransparentHugePages上述图表显示,当添加 JVM 标旗后,IPC 从 058 增加到 071。
成果
下表总结了性能改进所采取的措施及其结果。
JVM 选项集基准123IPC0606063071每千条指令的分支错过16141211每千条指令的 ITLB 错误83778811基准运行时间 [毫秒]6000392238433512执行时间相较于基准值得到改善。
parallelGCparallelGC tieredCompilationparallelGC tieredCompilation UseTransparentHugePages
发表评论