menu

CPU分析

PM2配备了可随时使用的CPU分析工具。 网络仪表板允许您在同一处分析所有服务器。 我们的可视化工具可帮助您可视化并解释分析您的结果,从而提高应用的性能。 分析文件也可以在Chrome开发工具中下载并检测。

为什么选择CPU分析?

CPU分析是诊断服务器CPU使用方式的工具。 CPU是每台计算机的核心部件,作为负责解释和执行几乎所有命令的组件,有时甚至可以被称为计算机的“大脑”。

Web服务器执行后端代码越多,需要的CPU功率就越多。 在静态内容Web服务器中,由于只有很少的操作在后端完成,因此计算量不大。 另一方面,在Web API的情况下,只有后端代码:CPU是实现高性能的核心。

除了获得尽可能高的CPU功率之外,只有通过优化代码才能提高API性能。 CPU分析提供了探寻在代码中如何跨功能使用CPU的功能。 一旦发现瓶颈,您就可以采取行动了。

数据采集

CPU分析如何工作?

探查器需要记录所有调用的函数以及CPU花费多长时间。

第一种方法是所谓的“仪器”。 该方法通过插入一段代码来计算调用次数并记录函数的执行时间。 这种方法的缺点是累赘。 它会影响很多代码的执行,即便它是精确的,它在活动的Web服务器内容上也是有问题的。

另一种方法是“抽样”。 在这种方法中,分析器以特定间隔中断代码执行并且每次都记录堆栈跟踪。 并非每个调用都被记录下来,但经过足够的时间后,得到的结论仍具有相关性。 这种方法最大的好处是它几乎不会影响代码执行,且可以在生产环境中使用。

一些分析器使用混合方法。 他们只用仪器代码来计算调用次数(一种廉价操作)并使用采样来衡量功能执行时间。

PM2分析器使用抽样方法。

数据表现

收集后,需要组织这样大量的数据,以便进行分析并提出问题。 以下是处理CPU分析结果的三种常用方法。

自上而下视图

自上而下视图显示方法调用的列表,展开方法节点显示其被调用者。

“自上而下”选项卡提供以下信息以帮助描述在每个方法调用上花费的CPU时间(时间也表示为所选时间范围内线程总时间的百分比):

Self:方法调用执行自己的代码的时间,而不是它的被调用者。 Children:方法调用花费在执行被调用者上的时间,而不是自己的代码。 总计:该方法的Self和Children时间的总和。 这表示应用程序执行方法调用所用的总时间。

自下而上视图

自下而上视图显示方法调用的列表,展开方法的节点显示其调用者。

自下而上视图对于那些消耗最多(或最少)CPU时间的方法排序很有用。 您可以检查每个节点,以确定哪些调用者花费大量CPU时间调用这些方法。 与自顶向下的树相比,底层树中每个方法的计时信息参照每个树顶部的方法(顶层节点)。 CPU时间也表示为该录制过程中线程总时间的百分比。 下表帮助解释了如何解释顶层节点及其调用方法(子节点)的时间信息。

火焰图

火焰图中的每个框代表堆叠中的一个功能。

y轴显示堆栈深度。 机顶盒显示CPU上的功能。 在那之下的一切都是ancestry。 函数下面的函数是它的主类,就像前面显示的堆栈跟踪一样。 X轴横跨样本总数。 它并不像大多数图表那样显示从左到右的时间流逝。 从左到右排序没有意义(它是按字母顺序的)。 框的宽度显示它在CPU上的总时间或CPU上的ancestry的一部分(基于样本数)。 使用宽框的功能可能会比使用窄框的功能消耗更多的CPU,或可能会更频繁地调用它们。 调用计数未显示(或通过采样已知)。 如果多个线程正在运行并同时采样,则样本计数可能会超过已用时间。 颜色不重要,通常随机挑选为暖色调(支持其他有意义的调色板)。 这种可视化被称为“火焰图”,因为它最初用于显示CPU上的热点,并且看起来像火焰。 它也是交互式的:将鼠标悬停在SVG上以显示细节,然后单击以放大。

如何解释结果?

让我们深入了解如何解释CPU分析以加快您的代码。 通过与源代码分析配对可以检测到以下情况:

  • 个别繁重的功能(例如排序功能);
  • 过度使用库函数(例如存储器复制函数);
  • 反复出现函数调用序列。

为了找到单独的重型功能,平面视图就足够了。 按自重和降序排序,这些功能将泡到顶端。 特别是如果他们的总重量接近自重(这意味着他们自完成所有工作),他们是优化的理想方法。 此方法适用于递归和非递归函数。

如果某个热门功能本身无法优化(例如,这是一个库函数),则自下而上的视图有助于查看其调用者。 获得最多权重的调用者(即最频繁调用函数的调用者),并查看源代码中为什么会过度使用该函数。 通常看起来,函数调用的结果可以被缓存,或可能有一种更有效的方法来做同样的事情,根本不需要调用函数。

按照总重量降序排列平视图,用自重排序次级视图也可以揭示由不适当导致重处理的功能。 考虑一个例子:假设我们看到一个函数top5',它有很大的总重量,但是自重很小。 现在我们从自顶向下的角度来看待它的被调用者,并且看到top5的时间大部分被占用于调用 qsort’。查看top5’源代码,我们发现这个调用是多余的,因为查找前5个数组项可以使用单个线性扫描来完成,而无需对数组进行排序。

调用图视图实际上可以用于所有这些情况,特别是如果可以调整它以基于其权重突出显示节点和边缘。 正如我所说,呼叫图的唯一问题在于它可能很大,因此需要一个好的可扩展方法来查看它。

但当我们想找到一个重复出现的函数调用序列时,一个调用图是真实可行的。 由于每个程序的功能只有一个相应的节点(不同于树视图),并且边具有权重,因此检测昂贵的序列相对容易。 在找到它们并查看函数的代码后,似乎通过函数计算的数据通常仅被部分使用,或甚至被调用者丢弃(当程序是从大型的可重用’通用’函数构建时发生的)。 编写一个不需要执行不必要计算的函数的特别版本可以大大加快程序的速度。