github.com/min1324/cmap@v1.0.3-0.20220418125848-74e72bbe3be4/README.md (about) 1 # cmap 2 [![Build Status](https://travis-ci.com/min1324/cmap.svg?branch=main)](https://travis-ci.com/min1324/cmap) [![codecov](https://codecov.io/gh/min1324/cmap/branch/main/graph/badge.svg)](https://codecov.io/gh/min1324/cmap) [![Go Report Card](https://goreportcard.com/badge/github.com/min1324/cmap)](https://goreportcard.com/report/github.com/min1324/cmap) [![GoDoc](https://godoc.org/github.com/min1324/cmap?status.png)](https://godoc.org/github.com/min1324/cmap) 3 4 ConcurrentMap (cmap) 是 **go** 分片加锁 map 的一种。它在通过减小锁的粒度和持有的时间来提高并发性。 5 6 ## 原理 7 8 ConcurrentMap 和 MutexMap 主要区别就是围绕着锁的粒度以及如何锁。如图 9 10 ![](doc/aab3105d-568e-3ce3-96c3-5ee2b854a494.jpeg) 11 12 左边便是MutexMap的实现方式---锁整个hash表;而右边则是ConcurrentMap的实现方式---锁桶(或段)。ConcurrentMap将hash表分为8个桶(默认值),诸如load,store,delete等常用操作只锁当前需要用到的桶。 13 14 ConcurrentMap中主要实体类就是三个:ConcurrentMap(整个Hash表),Node(节点),Bucket(桶),对应上面的图可以看出之间的关系。 15 16 ## grow 和 shrink 17 18 ### 扩容gorw 19 20 增加key后,hash表总key数量count满足条件:count > 1<<2*B,或在buckut储存的key数量size满足条件:size > 1<<(B+1),就会对hash表进行扩容。 21 22 ### 收缩shrink 23 24 删除key后,hash表总key数量count满足条件:count > initSize && count < 1<<(B-1),hash表进行收缩。 25 26 **扩容收缩操作:** 27 28 1. 将 resize 置为1。 29 2. newLen = 1<<B,申请新 node 。 30 3. 将旧node疏散到新node。 31 4. 完成疏散后,将旧node置空,resize置0。 32 33 34 ## compare 35 The `map` type in Go doesn't support concurrent reads and writes. 36 37 `cmap(concurrent-map)` provides a high-performance solution to this by sharding the map with minimal time spent waiting for locks. 38 39 The `sync.Map` has a few key differences from this map. The stdlib `sync.Map` is designed for append-only scenarios. 40 41 So if you want to use the map for something more like in-memory db, you might benefit from using our version. You can read more about it in the golang repo, for example [here](https://github.com/golang/go/issues/21035) and [here](https://stackoverflow.com/questions/11063473/map-with-concurrent-access) 42 43 _Here we fork some README document from [concurrent-map](https://github.com/orcaman/concurrent-map)_ 44 45 ## usage 46 47 Import the package: 48 49 ```go 50 import ( 51 "github.com/min1324/cmap" 52 ) 53 54 ``` 55 56 ```bash 57 go get "github.com/min1324/cmap" 58 ``` 59 60 The package is now imported under the "cmap" namespace. 61 62 ## example 63 64 ```go 65 66 // Create a new map. 67 var m cmap.Cmap 68 69 // Stores item within map, sets "bar" under key "foo" 70 m.Store("foo", "bar") 71 72 // Retrieve item from map. 73 if tmp, ok := m.Load("foo"); ok { 74 bar := tmp.(string) 75 } 76 77 // Deletes item under key "foo" 78 m.Delete("foo") 79 80 ``` 81 82 ## bench 83 84 85 86 | name | count | time | ps | allocs | 87 | :---------------------------------------------- | :-------- | :---------: | :--------: | :----------: | 88 | 读取大多数命中 | | | | | 89 | LoadMostlyHits/*cmap_test.DeepCopyMap-4 | 31570358 | 35.60 ns/op | 6 B/op | 0 allocs/op | 90 | LoadMostlyHits/*cmap_test.RWMutexMap-4 | 19840526 | 58.49 ns/op | 5 B/op | 0 allocs/op | 91 | LoadMostlyHits/*sync.Map-4 | 33907821 | 35.90 ns/op | 6 B/op | 0 allocs/op | 92 | LoadMostlyHits/*cmap.Map-4 | 20905459 | 57.21 ns/op | 6 B/op | 0 allocs/op | 93 | 读取大多数不命中 | | | | | 94 | LoadMostlyMisses/*cmap_test.DeepCopyMap-4 | 45099246 | 26.39 ns/op | 6 B/op | 0 allocs/op | 95 | LoadMostlyMisses/*cmap_test.RWMutexMap-4 | 22111984 | 54.36 ns/op | 6 B/op | 0 allocs/op | 96 | LoadMostlyMisses/*sync.Map-4 | 51615075 | 23.64 ns/op | 6 B/op | 0 allocs/op | 97 | LoadMostlyMisses/*cmap.Map-4 | 26444559 | 45.25 ns/op | 6 B/op | 0 allocs/op | 98 | 读写平衡 | | | | | 99 | LoadOrStoreBalanced/*cmap_test.RWMutexMap-4 | 2086924 | 557.8 ns/op | 89 B/op | 1 allocs/op | 100 | LoadOrStoreBalanced/*sync.Map-4 | 2409666 | 616.8 ns/op | 75 B/op | 2 allocs/op | 101 | LoadOrStoreBalanced/*cmap.Map-4 | 3032516 | 415.5 ns/op | 143 B/op | 1 allocs/op | 102 | 读写独立 | | | | | 103 | LoadOrStoreUnique/*cmap_test.RWMutexMap-4 | 1000000 | 1011 ns/op | 178 B/op | 2 allocs/op | 104 | LoadOrStoreUnique/*sync.Map-4 | 1000000 | 1280 ns/op | 163 B/op | 4 allocs/op | 105 | LoadOrStoreUnique/*cmap.Map-4 | 2135676 | 730.6 ns/op | 282 B/op | 2 allocs/op | 106 | 读写冲突 | | | | | 107 | LoadOrStoreCollision/*cmap_test.DeepCopyMap-4 | 56008429 | 20.92 ns/op | 0 B/op | 0 allocs/op | 108 | LoadOrStoreCollision/*cmap_test.RWMutexMap-4 | 7257867 | 163.1 ns/op | 0 B/op | 0 allocs/op | 109 | LoadOrStoreCollision/*sync.Map-4 | 44704843 | 26.09 ns/op | 0 B/op | 0 allocs/op | 110 | LoadOrStoreCollision/*cmap.Map-4 | 5274472 | 232.9 ns/op | 0 B/op | 0 allocs/op | 111 | 读删平衡 | | | | | 112 | LoadAndDeleteBalanced/*cmap_test.RWMutexMap-4 | 6776074 | 176.8 ns/op | 3 B/op | 0 allocs/op | 113 | LoadAndDeleteBalanced/*sync.Map-4 | 42597236 | 28.90 ns/op | 4 B/op | 0 allocs/op | 114 | LoadAndDeleteBalanced/*cmap.Map-4 | 17372445 | 66.46 ns/op | 4 B/op | 0 allocs/op | 115 | 读删独立 | | | | | 116 | LoadAndDeleteUnique/*cmap_test.RWMutexMap-4 | 6245928 | 192.7 ns/op | 7 B/op | 0 allocs/op | 117 | LoadAndDeleteUnique/*sync.Map-4 | 54371384 | 22.42 ns/op | 8 B/op | 0 allocs/op | 118 | LoadAndDeleteUnique/*cmap.Map-4 | 17595276 | 69.03 ns/op | 8 B/op | 0 allocs/op | 119 | 读删冲突 | | | | | 120 | LoadAndDeleteCollision/*cmap_test.DeepCopyMap-4 | 5193744 | 240.9 ns/op | 48 B/op | 1 allocs/op | 121 | LoadAndDeleteCollision/*cmap_test.RWMutexMap-4 | 8262384 | 147.3 ns/op | 0 B/op | 0 allocs/op | 122 | LoadAndDeleteCollision/*sync.Map-4 | 100000000 | 11.72 ns/op | 0 B/op | 0 allocs/op | 123 | LoadAndDeleteCollision/*cmap.Map-4 | 6053292 | 203.6 ns/op | 0 B/op | 0 allocs/op | 124 | 删除冲突 | | | | | 125 | DeleteCollision/*cmap_test.DeepCopyMap-4 | 5107717 | 212.8 ns/op | 48 B/op | 1 allocs/op | 126 | DeleteCollision/*cmap_test.RWMutexMap-4 | 8154603 | 144.8 ns/op | 0 B/op | 0 allocs/op | 127 | DeleteCollision/*sync.Map-4 | 92244220 | 12.90 ns/op | 0 B/op | 0 allocs/op | 128 | DeleteCollision/*cmap.Map-4 | 5844783 | 205.7 ns/op | 0 B/op | 0 allocs/op | 129 | 遍历 | | | | | 130 | Range/*cmap_test.DeepCopyMap-4 | 121210 | 10327 ns/op | 0 B/op | 0 allocs/op | 131 | Range/*cmap_test.RWMutexMap-4 | 19650 | 62535 ns/op | 16384 B/op | 1 allocs/op | 132 | Range/*sync.Map-4 | 111723 | 10640 ns/op | 0 B/op | 0 allocs/op | 133 | Range/*cmap.Map-4 | 47502 | 25803 ns/op | 33410 B/op | 64 allocs/op | 134 | | | | | | 135 | AdversarialAlloc/*cmap_test.DeepCopyMap-4 | 1648602 | 1626 ns/op | 276 B/op | 1 allocs/op | 136 | AdversarialAlloc/*cmap_test.RWMutexMap-4 | 15540801 | 74.92 ns/op | 8 B/op | 1 allocs/op | 137 | AdversarialAlloc/*sync.Map-4 | 3247868 | 387.6 ns/op | 49 B/op | 1 allocs/op | 138 | AdversarialAlloc/*cmap.Map-4 | 19950106 | 60.10 ns/op | 8 B/op | 1 allocs/op | 139 | | | | | | 140 | AdversarialDelete/*cmap_test.DeepCopyMap-4 | 2879204 | 437.9 ns/op | 168 B/op | 1 allocs/op | 141 | AdversarialDelete/*cmap_test.RWMutexMap-4 | 10290254 | 107.8 ns/op | 25 B/op | 1 allocs/op | 142 | AdversarialDelete/*sync.Map-4 | 5462886 | 218.0 ns/op | 34 B/op | 1 allocs/op | 143 | AdversarialDelete/*cmap.Map-4 | 23674045 | 49.53 ns/op | 8 B/op | 1 allocs/op | 144