@SovietPower
2023-02-04T20:21:40.000000Z
字数 1646
阅读 707
项目
共5部分,分别对无锁map、操作前获取锁map、sync.Map 进行测试:
注:
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkInsertM
BenchmarkInsertM-8 157 7122375 ns/op
BenchmarkInsertL
BenchmarkInsertL-8 157 7528680 ns/op
BenchmarkInsertS
BenchmarkInsertS-8 32 32121606 ns/op
BenchmarkUpdateM
BenchmarkUpdateM-8 372 3227915 ns/op
BenchmarkUpdateL
BenchmarkUpdateL-8 301 3862922 ns/op
BenchmarkUpdateS
BenchmarkUpdateS-8 84 14535339 ns/op
BenchmarkReadM
BenchmarkReadM-8 400 2913653 ns/op
BenchmarkReadL
BenchmarkReadL-8 342 3443182 ns/op
BenchmarkReadS
BenchmarkReadS-8 138 9800634 ns/op
BenchmarkDeleteM
BenchmarkDeleteM-8 780 1524906 ns/op
BenchmarkDeleteL
BenchmarkDeleteL-8 564 2217222 ns/op
BenchmarkDeleteS
BenchmarkDeleteS-8 174 7187940 ns/op
BenchmarkDeleteM2
BenchmarkDeleteM2-8 973 1269203 ns/op
BenchmarkDeleteL2
BenchmarkDeleteL2-8 621 1883041 ns/op
BenchmarkDeleteS2
BenchmarkDeleteS2-8 169 7703778 ns/op
对代码的理论分析:当操作不涉及dirty
时(读写的key都在read
中),只需要CASread
即可,不需要锁,效率高。
但结果总体和理论分析相差很大:
nil
或expunged
,直到dirty
覆盖read
,所以理论上大量删除read
后,read
这个map中依旧可能有大量元素,多少会影响哈希表的效率(删除测试1)。但实际上,未真正删除的数据影响并不大(删除测试2)。原因应该是由于环境为单线程,在并行压力大的情况下前两种情况应该都会有较大提升,同时加锁map性能会大幅下降。
sync.Map 适用场景:多线程压力大,读多写少,或程序中操作的键值集合变化不大。
理论上,只要不频繁插入新键,就能基本保持只用CAS而不需要锁。
在第一次新建dirty
时,需要拷贝read
,可能发生性能抖动。
注意和 Mutex 一样, sync.Map 也同样不能被复制,因为 atomic.Value 是不能被复制的。