为什么 perf 总是显示 _raw_spin_unlock_irqrestore 或其他一些自旋解锁功能

JC.*_*ang 5 linux-kernel spinlock perf

有谁知道为什么 perf 总是显示 _raw_spin_unlock_irqrestore 或其他一些自旋解锁功能?与 spin_lock 相比, spin_unlock 实现通常更简单。如果 spin_lock 上存在高竞争,那么 perf 不应该在 spin_lock 中显示结果吗?

Jon*_*ong 6

当中断被禁用时,perf用于采样的定时器中断不会触发。当中断最终被启用时(在任何irqrestore函数中),perf错误地计算整个时间跨度,就好像它被该恢复函数占用一样。

如果您更深入地查看使用perf annotate,您会看到大多数(如果不是全部)样本是 之后的 1 个操作码popfq,这会更新 EFLAGS 寄存器,从而启用中断:

_raw_spin_unlock_irqrestore  /proc/kcore
Percent?    Disassembly of section load0:
       ?
       ?    ffffffff819bd790 <load0>:
       ?      nop
       ?      push   %rbp
       ?      mov    %rsp,%rbp
       ?      movb   $0x0,(%rdi)
       ?      nop
       ?      mov    %rsi,%rdi
       ?      push   %rdi
       ?      popfq
100.00 ?      nop
       ?      pop    %rbp
       ?    ? retq
Run Code Online (Sandbox Code Playgroud)

Linux尝试使用 NMI进行性能监控中断。自 v2.6.31~ 以来,此更改在主线中,但我想它适用于裸机内核,而不适用于作为 VM 运行的内核(即,perf record在我的裸机 Linux 机器上没有出现此问题,而perf record在我机器上运行的 KVM 上则没有出现此问题做)。

有关更多详细信息,请参阅此答案


小智 2

你正在运行什么工作负载?您确定首先存在争议吗?

irq_restore 出现是因为重新启用中断的成本很高,但与中断一起使用的锁并不经常出现。当机器基本闲置时,您最有可能看到它。

为了好玩,我运行了一个微不足道的工作负载,该工作负载与自旋锁竞争,不出所料,显示最多的是锁定例程:

  81.36%  [kernel]                    [k] native_queued_spin_lock_slowpath
   4.67%  libc-2.17.so                [.] __memset_sse2
   1.63%  [kernel]                    [k] find_next_zero_bit
   0.92%  [kernel]                    [k] _raw_spin_lock
   0.81%  [kernel]                    [k] __audit_syscall_exit
   0.76%  [kernel]                    [k] __alloc_fd
   0.69%  [kernel]                    [k] __slab_free
   0.62%  [kernel]                    [k] security_compute_sid.part.13
   0.45%  [kernel]                    [k] kmem_cache_free
Run Code Online (Sandbox Code Playgroud)