返回

Perf 中如何仅过滤目标 CPU 核心上的用户态周期计数?

Linux

在 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 核心上的用户态周期计数。这有助于获得更准确的性能数据,从而更深入地了解应用程序的性能行为。

常见问题解答

  1. 为什么我需要固定进程到特定的 CPU 核心?

固定进程到特定的 CPU 核心可以防止其他核心干扰应用程序的性能,从而提供更可重复和一致的性能测量。

  1. 我可以使用 Perf 监视多个 CPU 核心上的用户态周期计数吗?

是的,可以通过省略 --cpu 选项来监视多个 CPU 核心上的用户态周期计数。但是,这可能会导致数据不准确,因为其他核心可能会执行其他任务。

  1. 如何确定要过滤的 CPU 核心?

要过滤的 CPU 核心取决于应用程序的行为和系统配置。可以通过使用 tophtop 等工具来监控 CPU 使用情况,以识别要过滤的 CPU 核心。

  1. Perf 是否支持其他计数器事件?

是的,Perf 支持广泛的计数器事件,包括缓存未命中、分支预测错误和指令已发出。可以使用 -e 选项指定要监视的事件。

  1. Perf 的其他有用的选项是什么?

Perf 提供了许多其他有用的选项,包括 --call-graph(显示调用图)、--flame-graph(显示火焰图)和 --report(生成报告)。