如何摆脱 perf 中的 "unknown" 部分

how to get rid of the "unknown" section in the perf

我做的是:

1. sudo rm -rf /root/.debug/
2. compile program with -g -O2 -fno-omit-frame-pointer
3. run the program and get the pid
4. sudo perf record -F 2000 -a -s -g -p $pid sleep 15
5. sudo perf report

然后我得到一小部分"unknown",比如

-    2.50%     0.00%  postgres  [unknown]            [k] 0000000000000000                                                                                                                                  
   - 0                                                                                                                                                                                                     
        1.12% _int_malloc                                                                                                                                                                                  ▒
        0.79% _IO_vsnprintf

看起来这是由于 libc 'malloc' 调用。然后我在同一台机器上写了一个程序来测试它。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    while(1) {
        printf("perf record -g -p %d -- sleep 5; perf report\n", getpid());
        sleep(1);
        void *p = malloc(10);
        memset(p, 0, 10);
        free(p);
    }
    return 0;
}

然后我和上面一样做了,没有"unknown"部分。

如何explain/fix这个?

perf report 输出中的 [unknown] 块引用动态共享对象的名称 (DSO)。 perf report 无法解析 DSO 路径,因此打印 [unknown]。根据最新的内核源代码树(在撰写本文时为 5.3.9),您可以看到 here.

重要的是要知道 DSO 符号的确定是在采样事件地址的帮助下发生的。函数 thread__resolve 负责执行此操作。在旧内核中,thread__resolve 方法有另一个名称 - perf_event__preprocess_sample_addr.

鉴于您的输出快照,在 perf record 期间采样的事件地址似乎为 0。这意味着该地址根本无法解析。它是内核中的一个地址space(查看符号[k] 0000000000000000),在你的情况下perf,无法解析它。

注释突出显示将 perf_event_paranoid 设置为合适的值,以便您可以成功探测内核和用户-space 事件。将 perf_event_paranoid 设置为允许您正确探测内核中事件的值 space 应该 "be a step" 正确解析地址。