Skip to content

Commit 16b0bf6

Browse files
committed
update mb
1 parent 2b8f1fb commit 16b0bf6

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

memory_barrier.md

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,20 +350,62 @@ func BenchmarkNormal(b *testing.B) {
350350
}
351351
}
352352

353+
func BenchmarkAtomicParallel(b *testing.B) {
354+
b.SetParallelism(100)
355+
b.RunParallel(func(pb *testing.PB) {
356+
for pb.Next() {
357+
atomic.StoreInt64(&a, int64(0))
358+
}
359+
})
360+
}
361+
353362
```
354363

364+
结果:
365+
355366
```shell
356-
go test -bench=.
357367
goos: darwin
358368
goarch: amd64
359-
BenchmarkAtomic-4 200000000 7.00 ns/op
360-
BenchmarkNormal-4 2000000000 0.39 ns/op
369+
BenchmarkAtomic-4 200000000 7.01 ns/op
370+
BenchmarkNormal-4 2000000000 0.63 ns/op
371+
BenchmarkAtomicParallel-4 100000000 15.8 ns/op
361372
PASS
362-
ok _/Users/xx/test/go/atomic_bench 2.925s
373+
ok _/Users/didi/test/go/atomic_bench 5.051s
363374
```
364375

376+
可见,atomic 耗时比普通赋值操作要高一个数量级,在有竞争的情况下会更加慢。
377+
365378
## false sharing / true sharing
366379

380+
true sharing 的概念比较好理解,在对全局变量或局部变量进行多线程修改时,就是一种形式的共享,而且非常字面意思,就是 true sharing。true sharing 带来的明显的问题,例如 RWMutex scales poorly 的官方 issue,即 RWMutex 的 RLock 会对 RWMutex 这个对象的 readerCount 原子加一。本质上就是一种 true sharing。
381+
382+
false sharing 指的是那些意料之外的共享。我们知道 CPU 是以 cacheline 为单位进行内存加载的,L1 的 cache line 大小一般是 64 bytes,如果两个变量,或者两个结构体在内存上相邻,那么在 CPU 加载并修改前一个变量的时候,会把第二个变量也加载到 cache line 中,这时候如果恰好另一个核心在使用第二个变量,那么在 P1 修改掉第一个变量的时候,会把整个 cache line invalidate 掉,这时候 P2 要修改第二个变量的话,就需要再重新加载该 cache line。导致了无谓的加载。
383+
384+
在 Go 的 runtime 中有不少例子,特别是那些 per-P 的结构,大多都有针对 false sharing 的优化:
385+
386+
runtime/time.go
387+
388+
```go
389+
var timers [timersLen]struct {
390+
timersBucket
391+
392+
// The padding should eliminate false sharing
393+
// between timersBucket values.
394+
pad [cpu.CacheLinePadSize - unsafe.Sizeof(timersBucket{})%cpu.CacheLinePadSize]byte
395+
}
396+
```
397+
398+
runtime/sema.go
399+
400+
```go
401+
var semtable [semTabSize]struct {
402+
root semaRoot
403+
pad [cpu.CacheLinePadSize - unsafe.Sizeof(semaRoot{})]byte
404+
}
405+
```
406+
407+
用户态的代码对 false sharing 其实关注的比较少。
408+
367409
参考资料:
368410

369411
https://homes.cs.washington.edu/~bornholt/post/memory-models.html

0 commit comments

Comments
 (0)