是什么原因导致仅用户空间进程的性能统计中出现内核内存操作?

问题描述 投票:0回答:1

我正在运行一个简单的程序,其中:

  1. 固定到 CPU 1 的线程从预分配和初始化的 2GB 内存区域执行随机读取,并且在内存访问循环期间不进行系统调用。
  2. Perf 在自己单独的进程中运行测量
    mem_inst_retired.all_loads:k,mem_inst_retired.all_stores:k -I 200 -p <pid>

这是最小的测试代码:

void access_memory(char *memory) {
    // Pin thread to CPU 1
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(1, &cpuset);
    pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);

    std::mt19937 gen(std::random_device{}());
    std::uniform_int_distribution<size_t> dist(0, 2GB - 500);
    char buffer[500];

    while (!should_stop) {
        size_t offset = dist(gen);
        memcpy(buffer, memory + offset, 500);
        buffer[0]++; 
    }
}

Plot showing high kernel load/stores likely because of perf

问题:

  1. 当进程只进行用户空间内存读取时,为什么会有内核内存操作?虽然这可能是观察者效应,但 PMU(性能监控单元)采样生成的中断是否会导致内核执行归因于访问过程的内存操作?我浏览了 SDM 但找不到好的答案。
  2. perf 如何将内核模式操作归因于特定进程?对于系统调用,很明显内核正在“代表”进程工作,但是调度、内存压缩或负载平衡等可能影响进程的内核任务又如何呢?它的界限在哪里?

我观察到,将采样间隔从 200 毫秒更改为 5 秒,会将每个间隔测量的内核操作从 ~10^5 操作更改为 ~10^7 操作。

以下是执行访问和测量加载/存储活动的简单代码: https://gist.github.com/VinayBanakar/8cd04c5fa03a6895292498d3e3687aac

c++ performance x86 cpu-architecture perf
1个回答
0
投票

中断处理程序不会从

current
任务进行上下文切换(直到/除非调度程序决定这样做),因此在定时器和外部硬件中断时,硬件性能计数器保持编程状态(在您的情况下计算内核存储指令)处理程序正在运行。

Linux 的 perf 子系统通过在上下文切换时保存/恢复来虚拟化 PMU(当不处于全系统模式时),就像虚拟化其他进程上下文一样。 每个核心变量

current
指向当前正在该核心上执行的任务。

perf stat
生成最少的中断,因为计数器可以编程为其支持的最高限制,因此溢出事件非常罕见。 与
perf record
不同,您想要足够频繁的中断来收集有意义的统计数据。

© www.soinside.com 2019 - 2024. All rights reserved.