PAS工具分享 - FrameScope与RTRadar
内容分析
1. PAS性能分析套件综述
2. PAS FrameScope
3. PAS RTRadar
01. PAS性能分析套件综述
这里引用了 Brendan Gregg 在其著作中对性能分析的总结。他指出,及时进行性能分析,可以使软件、硬件以及可配置项的优化迅速实施,从而使您的程序获得更优的执行效果。他将性能分析总结为三个步骤:Found 、 Fixed 和 Deployed 。 Found 阶段对应于我们常说的识别问题瓶颈;Fixed阶段是针对瓶颈制定修正方案;最后, Ddeploy 阶段是将方案规模化实施。 PAS 性能套件主要聚焦于 Found 阶段。
将性能分析比作走迷宫,我们在分析问题的初始阶段可能会面临众多潜在方向,需要不断试错。但如何在面对性能问题时,高效、快速、准确地找到解决方案呢?我们认为,这其实是可以遵循一定规律的。我们将优秀的性能分析行为定义为拆解步骤、层层递进的标准做法。下面是 Brendan 在2023年的一个演讲,他基于多年经验,对性能分析的认识进行了细致的步骤拆解,并对当前业内的性能分析进行了评分,满分5分。他还对各个环节进行了评价,感兴趣的读者可以在YouTube 上搜索这个演讲,内容非常精彩。当然,这种不好的分析行为在日常工作中非常常见。例如,有些同学在遇到问题时,习惯于直接在环境中开始分析,但他们缺少对案例的前置了解。比如我们举的例子,是网络领域的一个基准测试,称为 Network test ,其中包含两个进程。而下面列出的这两个任务案例,由于同学们缺少对测试案例的前置学习,导致他们未能正确观察到应该关注的性能线程,从而出现了观察错误。
02. PAS FrameScope
接下来,我们介绍 PAS 的一个子工具: Frame Scope ,刚才程东老师也提到了“ Frame ”这个关键词,我们的工具与之有一定关联。因为调用栈对我们来说是一个关键信息。程序运行的好坏,在微观层面上,对应于机器指令在 CPU 上的执行情况。从 CPU 角度评估程序运行好坏,可分为两个维度:一个维度是程序受 CPU 处理能力限制,即 on-CPU 问题,此时需关注 CPU 侧资源使用情况,它能真实反映程序运行情况;另一个维度是程序受 CPU 外其他资源限制时,业界称之为 off-CPU 问题,此时关注的不是 CPU 本身问题,而是 CPU外部资源使用情况,常见场景如 IO 阻塞。需明确, Frame Scope 是针对 on-CPU 场景的性能分析工具,通过采样方式,在采样时刻采集程序调用栈信息,结合 CPU 上各类 PMU 寄存器数据,经过数据加工处理,整合出各函数执行情况,呈现给开发者。
图中提到了 Frame Scope 的三大竞争优势:函数级微架构指标、多平台兼容性和多视图观测。为什么会有这三项竞争优势的总结?实际上,这三项优势都源于我们在日常生产生活中遇到的一些棘手问题。
场景一描述了微架构指标异常,但无法将其映射到具体实践。英特尔多年前提出了一套 Top-Down 流水线评估理论体系,适用于各种主流的 Pipeline 设计架构。但存在一个问题:目前主流的做法是对程序的开始和结束进行 PMU 采样统计,然后根据 Top-Down 公式计算指标。我们只能获得程序级别的 Top-Down 信息,对于开发者而言,这些信息确实有助于识别程序的种种短板,但开发者通常不清楚如何进行下一步优化。而 Frame Scope 赋予开发者的能力是将这套计算公式和指令映射到函数级别。使用 Frame Scope 工具时,可以为每个函数观测其 Top-Down 指标。分析程序时,可以通过函数过滤出前端或后端阻塞瓶颈较高的函数,从而有针对性地进行优化。
第二个问题是阿里云作为云服务提供商,我们的机房里部署了多种平台,以及不同代际的物理机,对外提供云服务。此时,我们通常需要回答集团内部业务和外部客户的问题:他们的业务在哪个平台上部署性价比最高。这就衍生出一个需求:需要对比多个平台。但我们面临的一个困境是,现有工具呈现离散化状态,难以统一方法论。对于业界大部分从业者来说,面对上述需求,他们需要投入大量时间和精力。首先,他们需要确定一个适用于不同平台对比的统一方法论,然后根据该方法论寻找支持或接近该方法论的工具,以采集所需的指标。最终整个过程十分冗长且不可靠。而 Frame Scope 性能分析工具套件的出发点是,在统一方法论的基础上,兼容各平台的性能分析需求。目前, Frame Scope 已在阿里云场景中支持主力机型的性能分析
第三个问题是工具上手难度大,指标难以理解。这是因为当前的性能工具要覆盖尽可能多的性能问题,其指标必然越来越多,工具设计的复杂度也随之增加。这样一来,对于开发者或使用者来说,学习成本非常高。我们的工具设计参考了业界主流工具,借鉴其设计思路,利用强大的 UI 特性将复杂指标进行强烈可视化。同时,我们会对这些指标进行高度封装和深入挖掘,将有用且有效的信息以更精简的方式呈现给每位开发者。我们展示了几个视图,这些是 Frame Scope 从不同层面和角度为开发者提供的视角。
接下来介绍几个 Frame Scope 在真实生产中的应用案例。第一个案例是日常生活中常见的一类问题:从调用栈上可以看到,两个调用栈帧明显存在异常凸起。 Frame Scope 具备调用栈可视化功能,可以轻松找到异常路径。对于异常路径,Frame Scope还提供了微架构识别功能。我截取了前端阻塞和后端阻塞的两个值,可以看到,调用栈上异常函数的后端阻塞远高于平均水平,说明它是一个瓶颈。这个问题比较容易总结:510系列内核产品使用了 SELINUX 的相关 CONFIG 控制,但在社区的6.x内核版本中,该CONFIG已逐步废弃,相关接口功能失效。这导致在产品代际升级时,一些预期内的控制路径失效,引发性能问题。我们的解决方法是在6.6内核产品的 Cmdline层面,加入 SELINUX 的 Cmdline 控制,以达到相同效果。
第二个案例是,在缺少对比或不熟悉程序时,面对众多热点, Frame Scope 能提供有效的分析能力。这个案例是关于 Unit Spanish 的Focus 测试。对于画红框的这两个函数,其后端阻塞明显达到90%,是一个明显的瓶颈点。在问题分析中,我们应优先分析这种主要矛盾。因此,我们优先对这两个函数进行深入分析,挖掘到了一些有价值的信息。两个函数都调用了 flash TRE 的配置函数,该函数本质上会执行 Flush TLB 操作,调用一些 TLB 指令。但在我们的场景中, Flush TLB指令是广播类型的,它会与关注范围内所有 CPU 进行交互。而我们实际上是一个单核测试场景,因此,这部分指令的实现是不必要的。因此,我们在该基础上进行了修改,在构建的场景中去掉了 Inner Shareable 关键字,修改了屏障指令相关部分,在 Unix Bench 的Focus 场景中,我们在一天的平台上获得了10%-15%的性能提升。这也体现了函数级 Top-Down 指标的导向性作用。
还有一个有趣的案例。正如之前提到的,我们的工具不仅适用于 ARM平台,在英特尔平台上也遇到了一个神奇的案例。这个案例来自 LLM bench test ,其诡异之处在于,一个逻辑相关的代码提交会影响测试用例的性能,导致性能波动。对于研发人员来说,代码逻辑令人难以理解。在最基础的情况下,对比了两个函数的热点后,我们并未发现任何差异,但其性能却明显下降。此时,我们借助 Frame Scope 工具,通过分析函数在其主路径上的 Select 函数,发现其Total前端阻塞在性能较差的场景中异常明显。随着信息的深入,我们进一步进行Top-Down 的 L 2、L 3 分析,最终定位到英特尔平台上的 Decode Icache 组件的影响。
简单介绍一下 Decode Icache ,它是在英特尔二代产品 Sandy Bridge 之后广泛应用的一个微架构组件。它的主要作用是在 E 码结束后、 V 码发射前,在传递过程中,数据来源于三个管道: Decode 、License Decode Pipeline 和 Miracle Code 。第一个就是刚才提到的Decode Icache ,第二个是传统疫苗管道,第三个是一些大型指令,可能翻译出超过4微码长度的会走一个特殊管道。我们需要关注的是,手册中提到,在大多数性能较好的场景中,微码的典型分布中,80%应来自Decode Icache 。但在性能劣化的场景中,我们发现 Decode Icache的利用率急剧下降。根本原因是代码提交导致主路径上函数的首地址偏移,进而导致热循环的地址偏移。在这个过程中,地址偏移会导致DSB 缓存受到影响。因为 DSB 缓存本身有特定规则,地址偏移后,有些未命中规则,使用效率会急剧下降。但大家不必过于担心,这种场景不会频繁发生。因为在热循环场景中,微码缓存的影响会被明显放大,但在常见的 E to E 场景中,我们尚未发现此问题。
以上就是我分享的所有内容,下面请苏峰同学分享。
03. PAS RTRadar
大家好,接下来由我来介绍 PAS 的另一个分离子工具 RTRadar。RTRadar 是我们开发的一个专门用于在系统层面进行事务或请求延迟分析的工具。
我们设计的出发点是跟踪请求或事务的完整执行流程。因此,我们需要解决的关键问题是如何跟踪事务,以及采集哪些数据。如果一个请求完全在 CPU 上执行,无需额外观测,只需采集其热点即可分析。对于实际业务而言,除了 on-CPU 情况,我们还需关注 off-CPU 情况。我们需要了解请求何时调度、何时阻塞等待,以及等待的事件和时长。
基于这些考量,我们在内核中采集两个重要时间点:一个是 Sched,我们需要跟踪其调度过程;另一个是 Wakeup ,通过它建立Waker和 Waking 的依赖关系。再通过 Wakeup 的调度栈,我们就能了解等待的资源。除了内核,我们还需跟踪应用程序,明确事务或请求的开始点和结束点。同时采集这些信息并导出至统一数据库。基于数据库数据,我们事后构建请求的全运行周期并进行分析统计。最后,我们实现了前端模块以提供信息输出和人机交互。因时间关系,我就不详细介绍具体实践了。
这页 PPT 展示的是 RTRadar 的输出视图。左侧展示请求的完整执行流程,包括关键事件、时间戳、各片段及其延迟占比,以及请求在不同线程间的转移过程和依赖关系。右上角是采集到的所有请求列表,基于此列表,可执行过滤和分类操作。右下角为统计视图,按类别统计各种影响因素,如 on-CPU、IO 和网络等,它们对整体延迟的贡献占比各是多少。这样我们就能明确哪些因素是关键的,然后可专门针对这些关键因素进行分析。
接下来我简单介绍两个使用 RTRadar 分析的性能案例。第一个是大家熟悉的 MySQL 写入场景,在阿里云 Alinux 3操作系统上。测试时发现其性能不如 CentOS 9 ,因此,我们用 RTRadar 跟踪了服务器端的写入执行过程。上面两张图展示了延迟分布。可以看到,在 P 90之前,绝大多数请求的延迟并无问题,与 CentOS 9相当,只有少数长尾请求的延迟较大。因此,我们将这部分案例专门过滤出来并进行统计。下面两张图展示了不同因素的贡献占比。可以看到 Alinux 3的调度延迟明显高于 CentOS 9,因此,我们排查了调度方面的因素。最后,我们发现一些默认调度参数设置可能较大,并进行了适应性调整,解决了 Alinux 3 的性能问题。
下一个案例相对复杂。我们在倚天平台上发现了 Specjbb 常规延迟较高的问题,同样,我们进行了跟踪和分类统计。这两张图展示了所有请求的分类统计情况和每个关键请求的统计情况。同样,在这两张图中可以看到调度延迟较高,因此,我们同样进行了调度延迟参数优化。但调整后 Specjbb 的性能仍未优化,因此,我们进行了深入分析。
接下来先介绍 Specjbb 的执行流程。左图展示了两个线程: IO 线程和工作线程。 IO 线程负责接收客户端请求,并进行简单序列化后传递给工作线程。工作线程执行计算任务后,将请求传递回 IO 线程,再由 IO 线程将响应发回客户端。左图展示了长尾请求的原始执行过程。我们发现这里有两大片段:工作线程的计算任务是纯 on-CPU 过程,而下面红框所示为 IO 线程的调度延迟等待,占比约60%,与前面的统计基本吻合。
右图展示了调整调度参数后的执行情况, IO 线程得到优化, IO 延迟几乎消失。但性能未提升的原因是工作线程执行时间变长,原本的纯 on-CPU 过程被多次调度打断。我们进一步分析了原始场景中 IO线程调度延迟长的原因,发现红框时间段内 CPU 并非忙碌,而是在空闲等待,原因是工作线程一直占用 CPU 。因此,我们得出结论:工作线程一直占用 CPU ,导致 IO 线程调度延迟长。如果调整调度参数,调度器会频繁打断工作线程。因此,我们发现这两种线程存在天然矛盾。
我们的解决方案是将 IO 线程和工作线程分别绑定,并按热点比例(约1:3)分配 CPU 。优化后,长尾延迟得以降低。最后统计发现,调度延迟降至20%左右,原先为60%多。
总结 RTRadar 的四大竞争力:
第一点,弥补了 Dapper 在单节点跟踪方面的不足。之前, Google提出了一个针对大型分布式系统的跟踪框架 Dapper ,可将瓶颈定位到单台机器,但未深入拆解。 RTRadar 弥补了单台机器跟踪的不足,未来若与 Dapper 结合,可实现真正的全链路跟踪。
第二点, RTRadar 能够梳理复杂业务的执行模式。例如 Specjbb 等复杂应用,大多数工程师其实并不清楚其具体的执行流程,以及各个线程如何配合和同步。 RTRadar 能够自动分析依赖关系,从而揭示出执行模式。
第三点, RTRadar 能够弥补 offCPU 火焰图中干扰因素较多的缺点。在日常分析 offCPU 场景时,一个常见问题是对于复杂应用,许多背景线程对性能的影响其实微乎其微。然而,我们无法区分哪些线程是有用的、哪些是无用的,因此只能对整个进程进行跟踪,这使得无用线程的 offCPU 占比过高,进而导致分析结果出现偏差。 RTRadar 通过其依赖分析功能,可以排除这些无关线程。
第四点,它能够准确定位延迟瓶颈及其影响因素。例如我们之前分享的两个案例,我们可以迅速获取存在瓶颈的请求和瓶颈片段,然后通过对其影响因素进行统计分析,从而定位到其原因。