Dante At2814
有什么 metrics 可以让我们知道「B因为A北改动从而在 cache 中实效了」?
我又用了三个月才学会怎么系统性调查 cpu cacheline false sharing,答案尽在 perf-c2c。
man 1 perf-c2c 的文档看不懂,没关系, https://joemario.github.io/blog/2016/09/01/c2c-blog/ 手把手包教包会。

让我们用 https://go.dev/play/p/-hMDKDWXbGE 这个简单的 go 程序作为用例,这个程序有两组 goroutines,其中没有 padding 的那组会造成大量 false sharing,但我们假装不知道,直接全局采样一秒:
perf c2c record -F 60000 -g -a -u -- sleep 1


然后检查输出
perf c2c report -NN -c pid,iaddr --full-symbols --stdio


第一部分 Trace Event Information 直接看 HITM (loads that hit in a modified cacheline)
  Load Local HITM                   :       1545
  Load Remote HITM                  :          0
  Load Remote HIT                   :          0


第二部分 Shared Data Cache Line Table 直接看 Tot Hitm
#        ----------- Cacheline ----------      Tot
# Index             Address  Node  PA cnt     Hitm 
# .....  ..................  ....  ......  ....... 
      0        0xc0000a0000     0    7447   97.67%


第三部分 Pareto 已经直接解析到源码了
#   Num  RmtHitm  LclHitm        Code address                Symbol            Object  Source:Line  Node{cpu list}
# .....  .......  .......  .................. .....................  ................  ...........  ....
           0.00%   91.12%            0x49ee14 [.] main.main.gowrap1  go_false_sharing  go.go:0       0{1-2}


注意 source line 解析有点问题,把 code address 0x49ee14 解析到了 go.go:0 显然是不对的,我们手动挡操作一下
$ gdb -p $(pidof go_false_sharing)
(gdb) disas/m 0x49ee14
58      atomic.AddUint64(&c[idx], 1)
   0x000000000049ee14 <+20>:  test   %al,(%rcx)
   0x000000000049ee16 <+22>:  lea    (%rcx,%rax,8),%rdx
   0x000000000049ee1a <+26>:  mov    $0x1,%ebx
   0x000000000049ee1f <+31>:  lock xadd %rbx,(%rdx)
=> 0x000000000049ee24 <+36>:  jmp    0x49ee14 <main.main.gowrap1+20>


因此确定了是 main.go:58 对 nopad counter 的 atomic add 导致了 91% 的 false sharing。
 
 
Back to Top