我又用了三个月才学会怎么系统性调查 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,但我们假装不知道,直接全局采样一秒:
然后检查输出
第一部分 Trace Event Information 直接看 HITM (loads that hit in a modified cacheline)
第二部分 Shared Data Cache Line Table 直接看 Tot Hitm
第三部分 Pareto 已经直接解析到源码了
注意 source line 解析有点问题,把 code address 0x49ee14 解析到了 go.go:0 显然是不对的,我们手动挡操作一下
因此确定了是 main.go:58 对 nopad counter 的 atomic add 导致了 91% 的 false sharing。
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。