@@ -5,8 +5,6 @@ package cmap
5
5
import (
6
6
"context"
7
7
"sync"
8
-
9
- "github.com/OneOfOne/cmap/hashers"
10
8
)
11
9
12
10
type (
@@ -21,8 +19,6 @@ const DefaultShardCount = 1 << 8
21
19
type CMap struct {
22
20
shards []* LMap
23
21
keysPool sync.Pool
24
- // HashFn allows using a custom hash function that's used to determain the key's shard. Defaults to DefaultKeyHasher.
25
- HashFn func (KT ) uint32
26
22
}
27
23
28
24
// New is an alias for NewSize(DefaultShardCount)
@@ -41,7 +37,6 @@ func NewSize(shardCount int) *CMap {
41
37
42
38
cm := & CMap {
43
39
shards : make ([]* LMap , shardCount ),
44
- HashFn : DefaultKeyHasher ,
45
40
}
46
41
47
42
cm .keysPool .New = func () interface {} {
@@ -59,63 +54,63 @@ func NewSize(shardCount int) *CMap {
59
54
60
55
// ShardForKey returns the LMap that may hold the specific key.
61
56
func (cm * CMap ) ShardForKey (key KT ) * LMap {
62
- h := cm . HashFn (key )
57
+ h := hasher (key )
63
58
return cm .shards [h & uint32 (len (cm .shards )- 1 )]
64
59
}
65
60
66
61
// Set is the equivalent of `map[key] = val`.
67
62
func (cm * CMap ) Set (key KT , val VT ) {
68
- h := cm . HashFn (key )
63
+ h := hasher (key )
69
64
cm .shards [h & uint32 (len (cm .shards )- 1 )].Set (key , val )
70
65
}
71
66
72
67
// SetIfNotExists will only assign val to key if it wasn't already set.
73
68
// Use `Update` if you need more logic.
74
69
func (cm * CMap ) SetIfNotExists (key KT , val VT ) (set bool ) {
75
- h := cm . HashFn (key )
70
+ h := hasher (key )
76
71
return cm .shards [h & uint32 (len (cm .shards )- 1 )].SetIfNotExists (key , val )
77
72
}
78
73
79
74
// Get is the equivalent of `val := map[key]`.
80
75
func (cm * CMap ) Get (key KT ) (val VT ) {
81
- h := cm . HashFn (key )
76
+ h := hasher (key )
82
77
return cm .shards [h & uint32 (len (cm .shards )- 1 )].Get (key )
83
78
}
84
79
85
80
// GetOK is the equivalent of `val, ok := map[key]`.
86
81
func (cm * CMap ) GetOK (key KT ) (val VT , ok bool ) {
87
- h := cm . HashFn (key )
82
+ h := hasher (key )
88
83
return cm .shards [h & uint32 (len (cm .shards )- 1 )].GetOK (key )
89
84
}
90
85
91
86
// Has is the equivalent of `_, ok := map[key]`.
92
87
func (cm * CMap ) Has (key KT ) bool {
93
- h := cm . HashFn (key )
88
+ h := hasher (key )
94
89
return cm .shards [h & uint32 (len (cm .shards )- 1 )].Has (key )
95
90
}
96
91
97
92
// Delete is the equivalent of `delete(map, key)`.
98
93
func (cm * CMap ) Delete (key KT ) {
99
- h := cm . HashFn (key )
94
+ h := hasher (key )
100
95
cm .shards [h & uint32 (len (cm .shards )- 1 )].Delete (key )
101
96
}
102
97
103
98
// DeleteAndGet is the equivalent of `oldVal := map[key]; delete(map, key)`.
104
99
func (cm * CMap ) DeleteAndGet (key KT ) VT {
105
- h := cm . HashFn (key )
100
+ h := hasher (key )
106
101
return cm .shards [h & uint32 (len (cm .shards )- 1 )].DeleteAndGet (key )
107
102
}
108
103
109
104
// Update calls `fn` with the key's old value (or nil) and assign the returned value to the key.
110
105
// The shard containing the key will be locked, it is NOT safe to call other cmap funcs inside `fn`.
111
106
func (cm * CMap ) Update (key KT , fn func (oldval VT ) (newval VT )) {
112
- h := cm . HashFn (key )
107
+ h := hasher (key )
113
108
cm .shards [h & uint32 (len (cm .shards )- 1 )].Update (key , fn )
114
109
}
115
110
116
111
// Swap is the equivalent of `oldVal, map[key] = map[key], newVal`.
117
112
func (cm * CMap ) Swap (key KT , val VT ) VT {
118
- h := cm . HashFn (key )
113
+ h := hasher (key )
119
114
return cm .shards [h & uint32 (len (cm .shards )- 1 )].Swap (key , val )
120
115
}
121
116
@@ -167,6 +162,19 @@ func (cm *CMap) Len() int {
167
162
return ln
168
163
}
169
164
165
+ // ShardDistribution returns the distribution of data amoung all shards.
166
+ // Useful for debugging the efficiency of a hash.
167
+ func (cm * CMap ) ShardDistribution () []float64 {
168
+ var (
169
+ out = make ([]float64 , len (cm .shards ))
170
+ ln = float64 (cm .Len ())
171
+ )
172
+ for i := range out {
173
+ out [i ] = float64 (cm .shards [i ].Len ()) / ln
174
+ }
175
+ return out
176
+ }
177
+
170
178
// KV holds the key/value returned when Iter is called.
171
179
type KV struct {
172
180
Key KT
@@ -217,6 +225,3 @@ func (cm *CMap) iterContext(ctx context.Context, ch chan<- *KV, locked bool) {
217
225
218
226
// NumShards returns the number of shards in the map.
219
227
func (cm * CMap ) NumShards () int { return len (cm .shards ) }
220
-
221
- // DefaultKeyHasher is an alias for hashers.TypeHasher32(key).
222
- func DefaultKeyHasher (key KT ) uint32 { return hashers .TypeHasher32 (key ) }
0 commit comments