在直线代码中指令引起的开销巨大的区别

3

我正在尝试理解Linux块层中[blk_account_io_completion][1]的开销。使用perf annotate,我得到了以下代码片段(删节版)。有人能否说明一下为什么addtest指令与它们同时执行的邻近指令相比具有如此大的开销呢?

         :                      part_stat_add(cpu, part, sectors[rw], bytes >> 9);
    0.13 :        ffffffff813336eb:       movsxd r8,r8d
    0.00 :        ffffffff813336ee:       lea    rdx,[rax*8+0x0]
    0.00 :        ffffffff813336f6:       mov    rcx,QWORD PTR [rdi+0x210]
   72.04 :        ffffffff813336fd:       add    rcx,QWORD PTR [r8*8-0x7e2df6a0]
    0.22 :        ffffffff81333705:       add    QWORD PTR [rcx+rdx*1],rsi
    0.61 :        ffffffff81333709:       mov    eax,DWORD PTR [rdi+0x1f4]
   26.52 :        ffffffff8133370f:       test   eax,eax
    0.00 :        ffffffff81333711:       je     ffffffff81333733 <blk_account_io_completion+0x83>
1个回答

3
可能的一个原因是,当采取样本时,这些指令恰好被指令指针所指向。典型的x86 CPU可以每个周期执行最多4条指令,但当它执行4条指令并且采取样本时,程序计数器只会指向其中一条指令,而不是这四条指令。
下面是一个例子-请参见以下内容。简单的循环,包含一堆nop指令。注意时钟滴答如何在具有三个间隙的配置文件中分布。这可能类似于您所看到的效果。
另外,也可能是mov rcx,QWORD PTR [rdi + 0x210]mov eax,DWORD PTR [rdi + 0x1f4]经常错过缓存,并将花费的周期归因于下一条指令,就像这里所看到的那样。
       │    区域 .text 的反汇编:
       │
       │    00000000004004ed :
       │      push   %rbp
       │      mov    %rsp,%rbp
       │      movl   $0x0,-0x4(%rbp)
       │    ↓ jmp    25
 14.59 │ d:   nop
       │      nop
       │      nop
  0.03 │      nop
 14.58 │      nop
       │      nop
       │      nop
  0.08 │      nop
 13.89 │      nop
       │      nop
  0.01 │      nop
  0.08 │      nop
 13.99 │      nop
       │      nop
  0.01 │      nop
  0.05 │      nop
 13.92 │      nop
       │      nop
  0.01 │      nop
  0.07 │      nop
 14.44 │      addl   $0x1,-0x4(%rbp)
  0.33 │25:   cmpl   $0x3fffffff,-0x4(%rbp)
 13.90 │    ↑ jbe    d
       │      pop    %rbp
       │    ← retq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接