跳转至正文

使用 CPU 探测视图

了解如何使用 DevTools 的 CPU 探测视图。

借助 CPU 探测视图,你可以记录并测量来自 Dart 或 Flutter 应用的会话。探测器可以帮助你解决性能问题,或者更好地理解应用的 CPU 活动。 Dart VM 收集 CPU 样本(在单个时间点上 CPU 调用栈的快照),并将数据发送给 DevTools 以进行可视化。通过聚合多个 CPU 样本,探测器可以帮助你了解 CPU 的大部分时间都花在了哪里。

CPU profiler(CPU 探测器)

#

点击 Record 开始记录一份 CPU profile。记录完成后,点击 Stop。此时, CPU 探测数据会从 VM 中拉取,并显示在探测视图中(Call tree、Bottom up、Method table 和 Flame chart)。

如果你想加载所有可用的 CPU 样本,而无需手动记录和停止,可以点击 Load all CPU samples,它会拉取 VM 已记录并存储在其样本缓冲区中的所有 CPU 样本,然后在探测视图中显示这些 CPU 样本。

默认情况下,VM 的样本缓冲区被用作环形缓冲区,这意味着一旦它被填满,新的样本就会开始覆盖缓冲区中最旧的样本。如果你想让 VM 在样本缓冲区被填满后丢弃此后收集的所有样本,请向 dart runflutter run 传递 --profile-startup 标记。

Bottom up(自底向上)

#

此表格提供了 CPU profile 的自底向上的呈现方式。这意味着自底向上表格中的每个顶层方法(即根节点),实际上是一个或多个 CPU 样本调用栈中的顶层方法。换句话说,自底向上表格中的每个顶层方法,都是自顶向下表格(即调用树)中的一个叶子节点。在此表格中,一个方法可以展开以显示它的 调用者

此视图有助于在 CPU profile 中识别开销较大的 方法。当此表格中某个根节点的 自身 时间较高时,意味着该 profile 中有许多 CPU 样本都以该方法位于调用栈顶层而结束。

请参阅下方的 参考线 小节,了解如何启用图中所示的蓝色和绿色竖线。

工具提示可以帮助你理解每一列中的值:

Total time(总时长)
对于自底向上树中的顶层方法(位于至少一个 CPU 样本顶层的栈帧),这是该方法用于执行其自身代码以及它所调用的任何方法的代码所花费的时间。

Self time(自身时长)
对于自底向上树中的顶层方法(位于至少一个 CPU 样本顶层的栈帧),这是该方法仅用于执行其自身代码所花费的时间。

对于自底向上树中的子级方法(即调用者),这是顶层方法(即被调用者)在通过该子级方法(即调用者)被调用时的自身时间。

表格元素(Self time(自身时长))

Screenshot of a bottom-up table

Call tree(调用树)

#

此表格提供了 CPU profile 的自顶向下的呈现方式。这意味着调用树中的每个顶层方法都是一个或多个 CPU 样本的根节点。在此表格中,一个方法可以展开以显示它的 被调用者

此视图有助于在 CPU profile 中识别开销较大的 路径。当此表格中某个根节点的 时间较高时,意味着该 profile 中有许多 CPU 样本都以该方法位于调用栈底层而开始。

Screenshot of a call tree table

请参阅下方的 参考线 小节,了解如何启用图中所示的蓝色和绿色竖线。

工具提示可以帮助你理解每一列中的值:

Total time(总时长)
一个方法用于执行其自身代码以及它所调用的任何方法的代码所花费的时间。

Self time(自身时长)
一个方法仅用于执行其自身代码所花费的时间。

Method table(方法表)

#

方法表为 CPU profile 中包含的每个方法提供了 CPU 统计信息。在左侧的表格中,所有可用的方法都会列出它们的 total(总)和 self(自身)时间。

Total(总)时间是一个方法在调用栈中 任何位置 所花费时间的总和,换句话说,就是一个方法用于执行其自身代码以及它所调用的任何方法的代码所花费的时间。

Self(自身)时间是一个方法在调用栈顶层所花费时间的总和,换句话说,就是一个方法仅用于执行其自身代码所花费的时间。

Screenshot of a call tree table

从左侧的表格中选择一个方法,会显示该方法的调用图。调用图会展示一个方法的调用者和被调用者,以及它们各自的调用者 / 被调用者百分比。

Flame chart(火焰图)

#

火焰图视图是 调用树 的图形化呈现。它是 CPU profile 的自顶向下视图,所以在此图中,最顶层的方法调用它下面的方法。每个火焰图元素的宽度表示一个方法在调用栈上所花费的时间。

与调用树类似,此视图有助于在 CPU profile 中识别开销较大的路径。

Screenshot of a flame chart

点击搜索栏旁边的 ? 图标可以打开帮助菜单,它提供了关于如何在图中导航和缩放的信息,以及一份颜色编码的图例。

CPU sampling rate(CPU 采样率)

#

DevTools 设定了一个 VM 收集 CPU 样本的速率:每 250 μs(微秒)1 个样本。在 CPU 探测器页面上,它默认被选为 “Cpu sampling rate: medium”。你可以使用页面顶部的选择器来修改这个速率。

Screenshot of cpu sampling rate menu

low(低)、medium(中)和 high(高)采样率分别为 1,000 Hz、4,000 Hz 和 20,000 Hz。了解修改此设置所带来的取舍是很重要的。

更高 的采样率记录的 profile 会产生一份更细粒度、样本更多的 CPU profile。这可能会影响你应用的性能,因为 VM 为了收集样本会被更频繁地中断。这也会导致 VM 的 CPU 样本缓冲区更快地溢出。 VM 用于存储 CPU 样本信息的空间是有限的。在更高的采样率下,这块空间会比使用更低采样率时更快地被填满并开始溢出。这意味着,你可能无法访问到所记录 profile 开头部分的 CPU 样本,具体取决于缓冲区是否在记录期间溢出。

以更低的采样率记录的 profile 会产生一份更粗粒度、样本更少的 CPU profile。它对你应用性能的影响较小,但你可能只能访问到关于 profile 期间 CPU 行为的较少信息。 VM 的样本缓冲区也会更慢地被填满,所以你可以看到应用运行更长时间段的 CPU 样本。这意味着你有更大的机会查看到所记录 profile 开头部分的 CPU 样本。

Filtering(过滤)

#

在查看 CPU profile 时,你可以按库、方法名或 UserTag 来过滤数据。

Screenshot of filter by tag menu

Guidelines(参考线)

#

在查看调用树或自底向上视图时,有时树的层级会非常深。为了帮助你在深层树中查看父子关系,请启用 Display guidelines 选项。它会在树的父级与子级之间添加竖向的参考线。

Screenshot of display options

其他资源

#

要了解如何使用 DevTools 分析计算密集型 Mandelbrot 应用的 CPU 使用情况,请查看 CPU 探测视图教程。此外,还可以了解应用在使用隔离区进行并行计算时的 CPU 使用情况。