Israel OgboleFrancesco Gualazzi

使用 Elastic Universal Profiling™ 解锁全系统可见性

了解如何通过堆栈跟踪、火焰图等获取快速、可操作的代码见解

14 分钟阅读
Unlocking whole-system visibility with Elastic Universal Profiling™

识别、优化、衡量、重复!

希望维护强大、高效的系统并实现最佳代码性能的 SRE 和开发人员需要有效的工具来衡量和改进代码性能。分析器对于这些任务来说是非常宝贵的,因为它们可以帮助您提高应用程序的吞吐量、确保系统可靠性以及更深入地了解代码在运行时的行为。然而,传统的分析器使用起来可能很麻烦,因为它们通常需要代码重新编译,并且仅限于特定语言。此外,它们还可能具有较高的开销,从而对性能产生负面影响,并使其不太适合在生产环境中进行快速的实时调试。

为了解决传统分析器的局限性,Elastic® 最近宣布 Elastic Universal Profiling 正式上市,这是一个持续分析产品,使用起来非常简单,无需插桩、重新编译或重启。此外,Elastic Universal Profiling 不需要主机上的调试符号,并且与语言无关,允许您分析在机器上运行的任何进程 — 从应用程序的代码到第三方库,甚至内核函数。

然而,即使是最先进的工具也需要一定水平的专业知识才能有效地解释数据。丰富的可视化分析数据(火焰图、堆栈跟踪或函数)最初可能会让人感到不知所措。这篇博文旨在揭秘持续分析,并指导您了解其独特的可视化效果。我们将为您提供从 Universal Profiling 中获取快速、可操作的见解的知识。

让我们开始吧。

堆栈跟踪:分析的基石

一切都从堆栈跟踪开始 — 捕捉函数调用级联的快照。

堆栈跟踪是应用程序在特定时间点的调用堆栈的快照。它捕获程序到目前为止所进行的函数调用序列。通过这种方式,堆栈跟踪充当调用堆栈的历史记录,允许您追溯到导致应用程序中特定状态的步骤。

此外,堆栈跟踪是分析器用来确定应用程序在任何给定时刻正在执行什么操作的基础数据结构。例如,当您的基础设施监控表明您的应用程序服务器正在消耗 95% 的 CPU 资源时,这一点尤其有用。虽然诸如 “top -H” 之类的实用程序可以显示消耗 CPU 最多的进程,但它们缺乏识别导致高使用率的特定代码行(在顶级进程中)所需的粒度。

在 Elastic Universal Profiling 的情况下,使用 eBPF 来对每个保持 CPU 内核繁忙的进程进行采样。与大多数仅关注应用程序代码的插桩分析器不同,Elastic Universal Profiling 提供全系统可见性 — 它不仅分析您的代码,还分析您不拥有的代码,包括第三方库,甚至内核操作。

下图显示了 Universal Profiling 代理程序在非常高的级别上的工作方式。步骤 5 指示将堆栈跟踪摄取到分析收集器中,这是 Elastic Stack 的一个新部分。

_ 只需 _ _ 部署分析主机代理程序 _ 并在几分钟后接收分析数据(在 Kibana®中)。 _ 立即开始 __ _

  1. Unwinder eBPF 程序(字节码)被发送到内核。

  2. 内核验证 BPF 程序是否安全。如果接受,该程序将附加到探针,并在事件发生时执行。

  3. eBPF 程序通过映射将收集的数据传递到用户空间。

  4. 代理程序从映射中读取收集的数据。从代理程序传输到映射的数据是进程特定的和解释器特定的元信息,这些信息有助于 eBPF unwinder 程序执行展开。

  5. 堆栈跟踪、指标和元数据被推送到 Elastic Stack。

  6. 通过 Kibana 将数据可视化为火焰图、堆栈跟踪和函数。

虽然堆栈跟踪是大多数分析工具的关键要素,但解释它们可能很棘手。让我们看一个简单的例子,让事情变得更容易一些。下表显示了来自 Java 应用程序的一组堆栈跟踪,并为每个堆栈跟踪分配了一个百分比,以指示其 CPU 时间消耗份额。

表 1:分组的堆栈跟踪,带有 CPU 时间百分比

百分比函数调用
60%startApp -> authenticateUser -> processTransaction
20%startApp -> loadAccountDetails -> fetchRecentTransactions
10%startApp -> authenticateUser -> processTransaction -> verifyFunds
2%startApp -> authenticateUser -> processTransaction ->libjvm.so
1%startApp -> authenticateUser -> processTransaction ->libjvm.so ->vmlinux: asm_common_interrupt ->vmlinux: asm_sysvec_apic_timer_interrupt

上面的百分比表示每个特定堆栈跟踪相对于在观察期内收集的堆栈跟踪总数的相对频率,而不是实际的 CPU 使用率百分比。此外,在诸如 Elastic Universal Profiling 之类的全系统分析器中,通常会观察到示例中的 libjvm.so 和内核帧 (vmlinux:*)。

此外,我们可以看到 60% 的时间花费在序列 startApp;authenticateUser; processTransaction 中。另外 10% 的处理时间分配给 verifyFunds,这是 processTransaction 调用的函数。鉴于这些观察结果,很明显,如果优化计划集中在 processTransaction 函数上,那么它将产生最大的影响,因为它是最昂贵的函数之一。然而,真实世界的堆栈跟踪可能比这个例子复杂得多。那么我们如何快速理解它们呢?这个问题的答案导致了火焰图的创建。

火焰图:堆栈跟踪的可视化

虽然上面的示例可能看起来很简单,但它几乎没有反映在持续的基础上跨多台机器聚合多个堆栈跟踪时遇到的复杂性。堆栈跟踪的深度和众多分支路径可能会使越来越难以确定代码消耗资源的位置。这就是火焰图(一个由 Brendan Gregg 推广的概念)发挥作用的地方。

火焰图是堆栈跟踪的可视化解释,旨在快速准确地识别消耗最多资源的函数。每个函数都用一个矩形表示,其中矩形的宽度表示在函数中花费的时间量,而堆叠的矩形的数量表示堆栈深度。堆栈深度是调用当前函数所调用的函数数量。

Elastic Universal Profiling 使用冰柱图,它是标准火焰图的反向变体。在冰柱图中,根函数位于顶部,其子函数显示在其父级下方 — 这样可以更容易地查看函数的层次结构以及它们之间的关系。

在大多数火焰图中,y 轴代表堆栈深度,但 x 轴没有标准化。一些分析工具使用 x 轴来表示时间的推移;在这些情况下,该图更准确地称为火焰图表。其他工具则按字母顺序对 x 轴进行排序。通用分析工具根据相对 CPU 使用率在 x 轴上对函数进行排序,从最消耗 CPU 时间的函数开始,从左到右排列,如下面的冰柱图示例所示。

调试和优化性能问题:堆栈跟踪、TopN 函数、火焰图

SRE 和 SWE 可以使用通用分析工具进行故障排除、调试和性能优化。它构建从内核到用户空间本机代码,再到更高层运行时中运行的代码的堆栈跟踪,使您能够识别性能回归减少浪费的计算更快地调试复杂问题

为此,通用分析工具提供三种主要的视图:堆栈跟踪、TopN 函数和火焰图。

堆栈跟踪视图

堆栈跟踪视图按线程、主机、Kubernetes 部署和容器显示分组的堆栈跟踪图。它可以用于检测线程中意外的 CPU 峰值,并深入到更小的时间范围,使用火焰图进行进一步调查。有关详细信息,请参阅文档

TopN 函数视图

通用分析工具的 TopN 函数视图显示最常采样的函数,按 CPU 时间、年度二氧化碳排放量和年度成本估算进行细分。您可以使用此视图来识别整个集群中最昂贵的函数,然后应用过滤器以专注于特定组件进行更详细的分析。单击函数名称会将您重定向到火焰图,使您可以检查调用层次结构。

火焰图视图

火焰图页面是您花费时间最多的地方,尤其是在调试和优化时。我们建议您使用以下指南来识别火焰图中的性能瓶颈和优化机会。三个关键要素,即需要关注的条件是宽度层次结构高度

宽度很重要:在冰柱图中,较宽的矩形表示函数占用更多的 CPU 时间。始终从左到右读取图形,并注意最宽的矩形,因为这些是主要的性能热点。

层次结构很重要:浏览图形的堆栈以了解函数关系。这种垂直检查将帮助您确定是一个函数还是多个函数导致了性能瓶颈。这还可以发现代码改进的机会,例如交换低效的库或避免不必要的 I/O 操作。

高度很重要:图形中较高或较长的堆栈通常指向较深的调用层次结构。这些可以表明代码结构复杂且效率较低,可能需要引起注意。

此外,在浏览火焰图时,您可能需要查找特定的函数名称以验证您关于它们存在的假设:在通用分析工具的火焰图视图中,视图左下角有一个“搜索”栏。您可以输入正则表达式,匹配项将在火焰图中突出显示;通过单击搜索栏旁边的左右箭头,您可以在火焰图中的匹配项之间移动,并找到匹配函数的调用者和被调用者。

总而言之,

  • 从左到右水平扫描,重点关注宽度,以查找 CPU 密集型函数。
  • 垂直检查以检查堆栈并发现瓶颈。
  • 查找高耸的堆栈以识别代码中潜在的复杂性。

总而言之,使用 TopN 函数生成优化假设,并使用堆栈跟踪和/或火焰图对其进行验证。使用堆栈跟踪来监视 CPU 使用率趋势并深入了解更精细的细节。使用火焰图快速调试和优化您的代码,使用宽度、层次结构和高度作为指导。

_识别。优化。衡量。重复!_

衡量您更改的影响

有史以来第一次,开发人员现在可以衡量每次部署的更改带来的性能(提高或降低)、云成本和碳足迹影响。

一旦您识别出性能问题并对代码应用了修复或优化,就必须衡量您的更改的影响。差异 TopN 函数和差异火焰图页面对于此至关重要,因为它们可以帮助您识别回归并衡量您的更改影响,不仅在性能方面,而且在碳排放量和成本节省方面。

“差异”列表示函数排名的变化。

您可能需要将标签或其他元数据(例如容器和部署名称)与时间范围结合使用,以区分优化后的更改和未优化的更改。

通用分析:优化应用程序资源的关键

从财务和环境可持续性的角度来看,计算效率不再仅仅是一种锦上添花,而是一种必须具备的要素。Elastic 通用分析工具提供了对所有应用程序运行时行为的前所未有的可见性,因此您可以识别和优化代码中资源最密集的区域。结果不仅是性能更好的软件,而且还减少了资源消耗、降低了云成本并减少了碳足迹。使用通用分析工具优化您的代码不仅对您的业务有利,而且对我们的世界也是正确的做法。

立即开始使用 Elastic 通用分析工具。

本文中描述的任何特性或功能的发布和时间安排仍由 Elastic 自行决定。任何当前不可用的特性或功能可能无法按时交付或根本无法交付。

分享这篇文章