我一直在寻找答案,但没有找到明确的答案。如何解释
perf report
输出中的第一行。事情是这样的:
Samples: 173M of event 'cache-misses', Event count (approx.): 461731712088
实际上我看过的每个教程都涵盖了除第一行之外的所有内容。 本页解释了样本和计数之间的差异,但我想百分百确定我没有在这里得出错误的结论:在我的示例中,
173M
和461731712088
是什么意思?根据我所读到的内容,我猜测第二个是运行时期间发生的缓存未命中总数,第一个是记录并用于显示统计信息的缓存未命中数。这是正确的还是我误解了输出?
你是对的。 对于硬件事件(不是页面错误和上下文切换等软件事件),
perf record
的工作原理是对 PMU 中的硬件计数器进行编程,以在每次出现 n
硬件事件时记录一个 样本。 (其中“记录样本”意味着写入 PEBS 缓冲区1 或只是当场引发中断。) 选择
n
是为了提供一定的采样频率,该频率不会导致太多中断而严重影响性能,但也会在运行您正在分析的任何内容的几秒钟到几分钟内收集该事件的合理数量的样本。 这可能意味着动态调整 n
,或者为不同的事件设置默认值。 (例如 instructions
,通常每个时钟发生超过 1 次,而 machine_clears.count
等非常罕见的事件。)
实际的 PMU 硬件使用
n
进行编程,并向 0 倒数(或者可能向 n
向上倒数并进行比较)。
perf stat
的工作原理是或多或少设置一个巨大的 n
,与硬件支持的一样大,因此它只需尽可能不频繁地中断计数器翻转。 并在最后收集最终的计数器值。 (软件可以随时读取/写入准确的计数;这就是内核在上下文切换上虚拟计数器的方式。)
但是
perf record
以及用于收集样本的 n
上的样本和数据文件只能从 samples * n
推断总计数,因此是“近似值”。
脚注 1:PEBS 缓冲区显然通常非常小,例如 1 个样本,因此它不会在中断上节省太多/根本,但它确实将样本精确地归因于一条指令,而不是附近的一条指令:请参阅滑块和https://www.brendangregg.com/perf.html 中的 PEBS 部分。 非常适合像
mem_load_retired.l3_miss
这样的活动。 像 cycles
这样的事件仍然必须选择一条指令来“责备”,而这通常是等待缓慢输入的指令,例如该指令尝试使用缓存未命中加载的结果,而不是加载本身。