简介
CPU 性能监视器跟踪提供程序可让用户使用 Fuchsia 跟踪系统访问内置于 CPU 中的性能计数器。
目前,只有 Intel 芯片组支持此功能。
在 Intel 上,性能监视器可向用户提供有关 CPU 的许多方面统计信息。如需查看可用于(例如Skylake 芯片:请参阅 Intel 第 3 卷第 19.2 章“第 6 代和第 7 代处理器的性能监控事件”。目前并非所有事件(或“计数器”)都已推出,但我们已经推出了许多事件,希望其中有一些对您有用。
示例如下:
- 每个 L1、L2、L3 的缓存命中/未命中次数
- 因缓存未命中而停止的周期
- 分支错误预测
- 已弃用说明
跟踪系统使用“类别”来让用户指定要收集哪些轨迹数据。Cpuperf 使用这些类别来简化要启用的硬件事件的规范。您可以在该目录中的 .inc
文件中找到完整的类别。下面介绍了一些代表性的类别。
如需收集轨迹数据,请在宿主机上运行 ffx trace start
,或直接在 Fuchsia 设备上运行 trace
。
示例:
$ categories="gfx"
$ categories="$categories,cpu:fixed:unhalted_reference_cycles"
$ categories="$categories,cpu:fixed:instructions_retired"
$ categories="$categories,cpu:l2_lines,cpu:sample:10000"
$ ffx trace start --buffer-size 64 --duration 2 --categories $categories
将 .fxt
文件保存到桌面后,您可以将其加载到 Perfetto 查看器中。
基本操作
性能数据收集的基本操作是为每个 CPU 的跟踪记录分配一个缓冲区,然后(在每个 CPU 上)设置一个计数器,以便在发生指定数量的事件后触发中断。此中断称为 PMI 中断(Performance Monitor 中断)。在 Intel 上,当计数器溢出时,中断会触发,此时中断服务例程会将各种信息(例如时间戳和程序计数器)写入轨迹缓冲区,重置计数器以便在预指定的事件数之后重新触发另一个中断,然后返回。
跟踪停止时,Cpuperf Trace Provider 会读取缓冲区,并将其转换为 Trace Manager 使用的轨迹格式。
当缓冲区填满时,跟踪也会停止。请注意,系统会使用内部缓冲区,因此(目前)不支持循环模式和流式传输模式。可收集的轨迹数据量取决于多种因素:
- 轨迹时长
- 缓冲区大小
- 采样频率
- 计数器溢出的频率
- 是否将程序计数器信息写入缓冲区
数据收集类别
如前所述,Fuchsia 跟踪系统使用“类别”来让用户指定要收集的数据。对于 CPU 跟踪,有一些类别可用于指定要启用的计数器、是否跟踪操作系统和/或用户空间,以及指定采样率。
如需详细了解每个性能计数器,请参阅 Intel 文档。本文档不会尝试提供有关每个计数器的详细信息。
采样率
系统会按照用户指定的速率收集每个计数器的数据。最终可以指定一个随机速率。在此期间,支持以下费率:
- cpu:sample:100
- cpu:sample:500
- cpu:sample:1000
- cpu:sample:5000
- cpu:sample:10000
- cpu:sample:50000
- cpu:sample:100000
- cpu:sample:500000
- cpu:sample:1000000
独立采样
默认情况下,系统会独立对每个计数器进行抽样。例如,如果请求“cpu:fixed:instructions_retired”和“arch:llc”(最后一级缓存 - L3),并将采样率设为 10000,则系统将每 10000 个“instruction retired”事件采样一次已退出的指令,并每 10000 个“LLC”事件采样一次 LLC 操作,前者发生的频率远高于后者。系统会收集每个样本的时间戳,这样就可以知道样本所用的时间,例如,淘汰了 10000 条指令。
基于时间的采样
有几个计数器可用作“时间基准”。 在时间基准模式下,一个计数器用于驱动所有计数器的数据收集,而不是每个计数器以自己的速率收集数据。这样可以更一致地了解正在发生的情况。另一方面,这样做意味着我们会放弃收集每个事件的统计 PC 数据(因为我们将获得的唯一 PC 值是基准时间事件的 PC 值)。除了时间基准计数器之外,还必须提供采样率。
请参阅下文,了解撰写本文之时的一组时基计数器,以及当前时基集的源代码树中的 src/performance/cpuperf_provider/intel-timebase-categories.inc
。
统计模式
统计模式是采样模式的更简单替代方案,它会在整个轨迹运行期间收集每个事件的计数,然后进行报告。
通过“cpu:tally”类别(而非“cpu:sample:*”类别)启用统计模式。
示例:
$ categories="cpu:l2_summary"
$ categories="$categories,cpu:fixed:unhalted_reference_cycles"
$ categories="$categories,cpu:fixed:instructions_retired"
$ categories="$categories,cpu:mem:bytes,cpu:mem:requests"
$ categories="$categories,cpu:tally"
$ ffx trace start --buffer-size 64 --duration 2 --categories $categories
选项
cpu:os - 收集在内核空间中运行的代码的数据。
cpu:user - 收集在用户空间中运行的代码的数据。
cpu:pc - 收集与每个事件相关的 PC 数据
例如,如果您想知道缓存未命中通常发生在何处(从统计角度来说,具体取决于采样率),这会非常有用。轨迹输出中包含每个采样点的地址空间和程序计数器。不过,这样做会使每个轨迹记录的大小翻倍,因此需要权衡利弊。
固定计数器
Intel 架构提供了三个“固定”计数器:
cpu:fixed:instructions_retired
cpu:fixed:unhalted_core_cycles
cpu:fixed:unhalted_reference_cycles
这些计数器是“固定”的,因为它们不使用可编程计数器。其中有三个,每个都有固定用途。它们的优势在于不会耗尽可编程计数器:系统有几十个计数器,但通常一次最多只能使用四个计数器,具体取决于型号。
可编程计数器
Skylake(和 Kaby Lake)芯片上有数十个可编程计数器。如需查看完整列表,请参阅 Intel 第 3 卷第 19.2 章“性能监控事件(针对第 6 代和第 7 代处理器)”。如需查看目前支持的平台列表,请参阅源代码树中的 zircon/system/ulib/zircon-internal/include/lib/zircon-internal/device/cpu-trace/intel-pm-events.inc
和 zircon/system/ulib/zircon-internal/include/lib/zircon-internal/device/cpu-trace/skylake-pm-events.inc
。
为简化可编程计数器的指定,这些计数器已被分组为源代码树中的 src/performance/cpuperf_provider/intel-pm-categories.inc
和 src/performance/cpuperf_provider/skylake-pm-categories.inc
中定义的类别。如需查看完整列表,请参阅这些文件。
一次只能指定其中一个类别。[稍后,我们将提供更多数据收集控制选项。]
少量实用类别:
cpu:arch:llc
- 最后一级缓存 (L3) 引用
- 最后一级缓存 (L3) 未命中
cpu:arch:branch
- 分支指令已停用
- 分支指令预测错误
cpu:skl:l1_summary
- 每个周期的未处理 L1D 缺失次数
- 此处理器核心上任何逻辑线程的未处理 L1D 缺失次数
- 提取到 L1 数据缓存的行数
cpu:skl:l2_summary
- 错失 L2 的需求请求
- 所有未命中 L2 的请求
- 向 L2 发出的所有需求数据读取请求
- 对 L2 的所有请求
cpu:skl:l3_summary
- 来自引用 L3 中缓存行的核心的请求
- 对 L3 的引用的缓存未命中条件
cpu:skl:offcore_demand_code
- 将 SQ 中未处理的离线需求代码读取事务的数量在每个周期递增到 uncore
- 在 SQ 中至少有 1 个非核心待处理需求代码读取事务的周期
cpu:skl:offcore_demand_data
- 在每个周期内递增 SQ 中核心未处理需求数据读取事务的数量,以取消核心
- 在 SQ 中至少有 1 个未处理的离核心需求数据读取事务的周期
- 在 SQ 中至少有 6 个未处理的离核心需求数据读取事务的周期
cpu:skl:l1_miss_cycles
- L1 数据未达需求负载未完成时循环
- 在 L1 数据缺失需求加载待处理时,执行会暂停
cpu:skl:l2_miss_cycles
- L2 缺失需求载荷待处理时的周期
- 当 L2 未命中需求负载未完成时,执行会停止
cpu:skl:l3_miss_cycles
- L3 未达需求负载未完成时的周期
- 当 L3 未命中需求负载未完成时,执行会停止
cpu:skl:mem_cycles
- 内存子系统有未处理的负载时的周期
- 在内存子系统有未处理的负载时,执行会暂停
时间基准计数器
这些计数器可用作时间基准。我们会及时添加更多产品。
cpu:timebase:fixed:instructions_retired
- 计数器与 cpu:fixed:instructions_retired 相同
cpu:timebase:fixed:unhalted_reference_cycles
- 计数器与 cpu:fixed:unhalted_reference_cycles 相同