性能问答>一个Linux中 单独用户空间/内核空间中的 Perf 指令/周期计数问题>
6回复
5月前

一个Linux中 单独用户空间/内核空间中的 Perf 指令/周期计数问题



在用 perf 分析具有用户空间和内核空间代码的应用程序时,启用各种内核配置的所有其他可能性,但无法单独获得用户空间/内核空间中的指令/周期数。

于是尝试使用 ":u" 和 ":k" 扩展指令和周期计数,但我得到的结果是:

$ perf stat -e cycles:u,instructions:u ls

 Performance counter stats for 'ls':

   <not supported>      cycles:u

   <not supported>      instructions:u

       0.006047045 seconds time elapsed

       0.000000000 seconds user
       0.008098000 seconds sys

但是,仅针对循环/指令运行又给出如下所示的正确结果。

$ perf stat -e cycles,instructions ls

 Performance counter stats for 'ls':

          5362086      cycles
            528783      instructions              #    0.10  insn per cycle

       0.005487940 seconds time elapsed

       0.007800000 seconds user
       0.000000000 seconds sys

ps:

1,ls 在这里只是作为一个例子来突出这个问题。

2,运行的是 Linux 5.4 和 perf 版本 5.4.77.g1206eede9156,而且在 ARM 板上运行上述命令。

下面是在 Linux 内核中启用的配置:

CONFIG_PERF_EVENTS=y
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
CONFIG_KPROBES=y
CONFIG_OPTPROBES=y
CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_FRAME_POINTER=y
CONFIG_FTRACE=y
CONFIG_KPROBE_EVENTS=y
CONFIG_UPROBE_EVENTS=y
CONFIG_PROBE_EVENTS=y

此外,命令行上的 perf list 列出了硬件/软件事件等等

$ perf list
  branch-instructions OR branches                    [Hardware event]
  branch-misses                                      [Hardware event]
  cache-misses                                       [Hardware event]
  cache-references                                   [Hardware event]
  cpu-cycles OR cycles                               [Hardware event]
  instructions                                       [Hardware event]
  alignment-faults                                   [Software event]
  bpf-output                                         [Software event]
  context-switches OR cs                             [Software event]
  cpu-clock                                          [Software event]
  cpu-migrations OR migrations                       [Software event]
  dummy                                              [Software event]
  emulation-faults                                   [Software event]
  major-faults                                       [Software event]
  minor-faults                                       [Software event]
  page-faults OR faults                              [Software event]
  task-clock                                         [Software event]
  duration_time                                      [Tool event]
  L1-dcache-load-misses                              [Hardware cache event]
  L1-dcache-loads                                    [Hardware cache event]
  L1-dcache-prefetch-misses                          [Hardware cache event]
  L1-dcache-prefetches                               [Hardware cache event]
  L1-dcache-store-misses                             [Hardware cache event]
  L1-dcache-stores                                   [Hardware cache event]
  L1-icache-load-misses                              [Hardware cache event]
  L1-icache-loads                                    [Hardware cache event]
  L1-icache-prefetch-misses                          [Hardware cache event]
  L1-icache-prefetches                               [Hardware cache event]
  branch-load-misses                                 [Hardware cache event]
  branch-loads                                       [Hardware cache event]
  dTLB-load-misses                                   [Hardware cache event]
  dTLB-store-misses                                  [Hardware cache event]
  iTLB-load-misses                                   [Hardware cache event]

那应该如何解决此问题?是我哪里做错了什么吗?

189 阅读
请先登录,再评论

444,022 cycles:u和perf stat -e cycles:u ls的关系是相互依存的, 在 Linux 5.12.15-arch1-1 上perf 版本是5.13.g62fb9874f5da,,在裸机 (x86-64 Skylake) 上才会带有perf_event_paranoid=0.(如果使用现代 perf,perf stat --all-user还可以用于暗示:u所有事件。)

我猜你的 ARM CPU 的硬件性能计数器不支持使用权限级别的掩码进行编程,因此perf报告说没有硬件计数器能够仅计算用户空间指令。

就我所知,在每个中断入口点都没有钩子来启用/禁用硬件计数器,而是仅计算内核、仅用户或两者,所以纯粹是硬件功能。

硬件支持对于准确计数显然必不可少,因为在软件实现中,计数器仍会计数,直到内核代码运行保存当前计数。(另外在恢复状态之后,返回用户空间之前的内核代码。)

此外,它会使每个中断和系统调用更加昂贵,而不仅仅是通过在任务/线程之间的每个上下文切换中保存/恢复它们来虚拟化性能计数器。因此,即使在没有硬件支持特权掩码的 CPU 上,内核也有充分的理由不支持在软件中进行松散的尝试。

5月前
回复 金色梦想:

哦哦,再次感谢!

5月前回复
回复 RVR:

应该是IDK,关于perf record输出之前稍微了解过。

5月前回复
回复 RVR:

再次感谢大佬的解释。还有个问题请教,想知道对 kernel.kallsyms 的调用是什么?因为我在运行 record 命令时看到它们被列出来了,还有就是来自程序/库的任何其他系统调用都将列在 kernel.kallsyms 下么?

5月前回复
查看更多