Perf 中如何仅过滤目标 CPU 核心上的用户态周期计数?
2024-03-30 09:45:56
在 Perf 中仅过滤目标 CPU 核心上的用户态周期计数
前言
Perf 是一个强大的工具,用于剖析和分析计算机系统的性能。然而,当应用程序固定到特定的 CPU 核心时,Perf 输出可能会显示来自所有 CPU 核心上的用户态周期计数,这可能会造成混淆和不准确。本文将探讨如何使用 Perf 仅过滤目标 CPU 核心上的用户态周期计数,从而获得更准确的性能数据。
问题:为什么 Perf 默认显示所有 CPU 核心的计数?
默认情况下,Perf 会收集所有 CPU 核心上的计数器数据。即使应用程序固定到特定核心,其他核心仍可能在执行系统任务或其他进程的指令。因此,cycles:u
事件可能会显示在所有核心上,即使应用程序仅在目标核心上执行用户态指令。
解决方案:使用 --pid
和 --cpu
选项
为了仅过滤目标 CPU 核心上的用户态周期计数,我们需要结合使用 --pid
和 --cpu
选项。
--pid
选项: 此选项用于指定要监视的进程的 PID。这将确保 Perf 仅收集目标进程的计数器。--cpu
选项: 此选项用于指定要过滤的 CPU 核心。这将进一步过滤仅来自目标 CPU 核心的计数器。
示例命令
以下命令演示了如何使用 --pid
和 --cpu
选项仅过滤目标 CPU 核心 0 上的进程 12345 的用户态周期计数:
sudo perf stat -e cycles:u --cpu=0 --pid=12345 --delay=1000 ./app
-e cycles:u
:指定要监视的用户态周期计数事件。--cpu=0
:指定要过滤的 CPU 核心 0。--pid=12345
:指定要监视的进程 PID 12345。--delay=1000
:指定 Perf 在退出之前运行的时间量,以毫秒为单位。
代码示例:固定进程到特定的 CPU 核心
为了确保应用程序仅在目标 CPU 核心上运行,可以使用 sched_setaffinity()
系统调用将其固定到特定的 CPU 亲和性掩码。以下是 C 代码示例:
#include <sched.h>
int main()
{
// 获取当前进程的 PID
pid_t pid = getpid();
// 定义 CPU 亲和性掩码,仅允许在核心 0 上运行
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
// 将进程固定到 CPU 亲和性掩码
int ret = sched_setaffinity(pid, sizeof(cpuset), &cpuset);
if (ret != 0) {
perror("sched_setaffinity() failed");
return -1;
}
// 进入无限循环,执行用户态指令
while (true) {}
return 0;
}
结论
通过结合使用 --pid
和 --cpu
选项,可以仅过滤目标 CPU 核心上的用户态周期计数。这有助于获得更准确的性能数据,从而更深入地了解应用程序的性能行为。
常见问题解答
- 为什么我需要固定进程到特定的 CPU 核心?
固定进程到特定的 CPU 核心可以防止其他核心干扰应用程序的性能,从而提供更可重复和一致的性能测量。
- 我可以使用 Perf 监视多个 CPU 核心上的用户态周期计数吗?
是的,可以通过省略 --cpu
选项来监视多个 CPU 核心上的用户态周期计数。但是,这可能会导致数据不准确,因为其他核心可能会执行其他任务。
- 如何确定要过滤的 CPU 核心?
要过滤的 CPU 核心取决于应用程序的行为和系统配置。可以通过使用 top
或 htop
等工具来监控 CPU 使用情况,以识别要过滤的 CPU 核心。
- Perf 是否支持其他计数器事件?
是的,Perf 支持广泛的计数器事件,包括缓存未命中、分支预测错误和指令已发出。可以使用 -e
选项指定要监视的事件。
- Perf 的其他有用的选项是什么?
Perf 提供了许多其他有用的选项,包括 --call-graph
(显示调用图)、--flame-graph
(显示火焰图)和 --report
(生成报告)。