go 别让性能被“锁”住
2022年1月19日1.如果一直是读的情况下不要加锁影响性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
package lock_test import ( "fmt" "sync" "testing" ) var cache map[string]string const NUM_OF_READER int = 40 //进程数量 const READ_TIMES = 100000 //读取次数 func init() { cache = make(map[string]string) cache["a"] = "aa" cache["b"] = "bb" } func lockFreeAccess() { var wg sync.WaitGroup wg.Add(NUM_OF_READER) for i := 0; i < NUM_OF_READER; i++ { go func() { for j := 0; j < READ_TIMES; j++ { _, err := cache["a"] if !err { fmt.Println("Nothing") } } wg.Done() }() } wg.Wait() } func lockAccess() { var wg sync.WaitGroup wg.Add(NUM_OF_READER) m := new(sync.RWMutex) for i := 0; i < NUM_OF_READER; i++ { go func() { for j := 0; j < READ_TIMES; j++ { m.RLock() //读锁上 _, err := cache["a"] if !err { fmt.Println("Nothing") } m.RUnlock() //读完解锁 } wg.Done() }() } wg.Wait() } func BenchmarkLockFree(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { lockFreeAccess() } } func BenchmarkLock(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { lockAccess() } } |
三种锁 读写锁
concurrent_map_benchmark_adapter.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package maps import "github.com/easierway/concurrent_map" /** * 声明结构, 引入实现interface */ type ConcurrentMapBenchmarkAdapter struct { cm *concurrent_map.ConcurrentMap } /** * 实现设置方法 */ func (m *ConcurrentMapBenchmarkAdapter) Set(key interface{}, value interface{}) { m.cm.Set(concurrent_map.StrKey(key.(string)), value) } /** * 实现获取方法 */ func (m *ConcurrentMapBenchmarkAdapter) Get(key interface{}) (interface{}, bool) { return m.cm.Get(concurrent_map.StrKey(key.(string))) } /** * 实现删除方法 */ func (m *ConcurrentMapBenchmarkAdapter) Del(key interface{}) { m.cm.Del(concurrent_map.StrKey(key.(string))) } /** * 创建一个 ConcurrentMapBenchmarkAdapter */ func CreateConcurrentMapBenchmarkAdapter(numOfPartitions int) *ConcurrentMapBenchmarkAdapter { conMap := concurrent_map.CreateConcurrentMap(numOfPartitions) return &ConcurrentMapBenchmarkAdapter{conMap} } |
sync_map_benchmark_adapter.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package maps import "sync" /** * 声明结构, 引入实现interface */ type SyncMapBenchmarkAdapter struct { m sync.Map } /** * 实现设置方法 */ func (m *SyncMapBenchmarkAdapter) Set(key interface{}, val interface{}) { m.m.Store(key, val) } /** * 实现获取方法 */ func (m *SyncMapBenchmarkAdapter) Get(key interface{}) (interface{}, bool) { return m.m.Load(key) } /** * 实现删除方法 */ func (m *SyncMapBenchmarkAdapter) Del(key interface{}) { m.m.Delete(key) } /** * 创建一个 SyncMapBenchmarkAdapter */ func CreateSyncMapBenchmarkAdapter() *SyncMapBenchmarkAdapter { return &SyncMapBenchmarkAdapter{} } |
rw_map.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package maps import "sync" /** * 声明结构, 引入实现interface */ type RWLockMap struct { m map[interface{}]interface{} lock sync.RWMutex } /** * 实现获取方法 */ func (m *RWLockMap) Get(key interface{}) (interface{}, bool) { m.lock.RLock() v, ok := m.m[key] m.lock.RUnlock() return v, ok } /** * 实现设置方法 */ func (m *RWLockMap) Set(key interface{}, value interface{}) { m.lock.Lock() m.m[key] = value m.lock.Unlock() } /** * 实现删除方法 */ func (m *RWLockMap) Del(key interface{}) { m.lock.Lock() delete(m.m, key) m.lock.Unlock() } /** * 创建一个 RWLockMap */ func CreateRWLockMap() *RWLockMap { m := make(map[interface{}]interface{}, 0) return &RWLockMap{m: m} } |
测试 map_benchmark_test.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package maps import ( "strconv" "sync" "testing" ) const ( NumOfReader = 10 NumOfWriter = 100 ) type Map interface { Set(key interface{}, val interface{}) Get(key interface{}) (interface{}, bool) Del(key interface{}) } func benchmarkMap(b *testing.B, hm Map) { for i := 0; i < b.N; i++ { var wg sync.WaitGroup for i := 0; i < NumOfWriter; i++ { wg.Add(1) go func() { for i := 0; i < 100; i++ { hm.Set(strconv.Itoa(i), i*i) hm.Set(strconv.Itoa(i), i*i) hm.Del(strconv.Itoa(i)) } wg.Done() }() } for i := 0; i < NumOfReader; i++ { wg.Add(1) go func() { for i := 0; i < 100; i++ { hm.Get(strconv.Itoa(i)) } wg.Done() }() } wg.Wait() } } func BenchmarkSyncmap(b *testing.B) { b.Run("map with RWLock", func(b *testing.B) { hm := CreateRWLockMap() benchmarkMap(b, hm) }) b.Run("sync.map", func(b *testing.B) { hm := CreateSyncMapBenchmarkAdapter() benchmarkMap(b, hm) }) b.Run("concurrent map", func(b *testing.B) { superman := CreateConcurrentMapBenchmarkAdapter(199) benchmarkMap(b, superman) }) } |