当我比较sync.mu、sync.Map和atomic.Value在go中的效率时,预期sync.mu比后两者的效率要低。但当我进行基准测试时,发现使用sync.mu的执行时间较短。所以我想知道原因,或者有最好的做法。
码
源代码在这里,https://go.dev/play/p/WODF8Tyyw4d将其简化如下:
sync.Map:
sync.mu与Scene1// sync.mu reader
mu.Lock()
tmp := tA[idx]
mu.Unlock()
// sync.mu writer
mu.Lock()
tA[idx] = data
mu.Unlock()
// sync.Map reader
v, _ := tB.Load(idx)
// sync.Map writer
tB.Store(idx, data)atomic.Value:
sync.mu与// sync.mu reader
mu.Lock()
tmp := tA[0]
mu.Unlock()
// sync.mu Writer
mu.Lock()
tA = data
mu.Unlock()
// atomic.Value reader
v := tC.Load().(map[int]int)[0]
// atomic.Value writer
tC.Store(data)结果
goos: darwin
goarch: amd64
pkg: sync-demo
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkMu-12 1000000000 0.5401 ns/op
BenchmarkSyncMap-12 1000000000 0.5504 ns/op
BenchmarkMuTotal-12 1000000000 0.5418 ns/op
BenchmarkAtomic-12 1000000000 0.5457 ns/op
PASS
ok sync-demo 64.195s发布于 2022-03-27 11:52:07
您并不是在限制这种同步结构的效率,因为您也是doind I/0。此外,在这个代码…中还有goroutines和等待组。不知道我是否理解
您应该考虑在相同的上下文中比较类似的用法。
例如,增加一个计数器。在sync.Map,atomic.Value中有一个计数器,由互斥锁保护。
每种方法都有优缺点,但互斥锁只处理同步,而其他结构也处理存储。
Mutex应该更快,因为它是…不那么复杂。
但是,如果您处理的东西比uint64更复杂,那么atomic.Value的开销可能是可以的。
例如,使用互斥锁,您需要一个特定的锁/解锁顺序,并且您可能在没有适当的测试+竞争条件检测器的情况下发现一些问题。
atomic.Value会帮你处理这件事。
我从不使用sync.Map,但是我在生产中使用了atomic.Value非常高效的代码--我对此很满意。
正确的基准需要一种更技术性的方法。
https://stackoverflow.com/questions/71635678
复制相似问题