github.com/scottcagno/storage@v1.8.0/pkg/hashmap/openaddr/rhhmap_test.go (about) 1 package openaddr 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/scottcagno/storage/pkg/bits" 7 "github.com/scottcagno/storage/pkg/util" 8 "math/rand" 9 "strconv" 10 "testing" 11 ) 12 13 // 25 words 14 var words = []string{ 15 "reproducibility", 16 "eruct", 17 "acids", 18 "flyspecks", 19 "driveshafts", 20 "volcanically", 21 "discouraging", 22 "acapnia", 23 "phenazines", 24 "hoarser", 25 "abusing", 26 "samara", 27 "thromboses", 28 "impolite", 29 "drivennesses", 30 "tenancy", 31 "counterreaction", 32 "kilted", 33 "linty", 34 "kistful", 35 "biomarkers", 36 "infusiblenesses", 37 "capsulate", 38 "reflowering", 39 "heterophyllies", 40 } 41 42 func Test_defaultHashFunc(t *testing.T) { 43 set := make(map[uint64]string, len(words)) 44 var hash uint64 45 var coll int 46 for _, word := range words { 47 hash = defaultHashFunc(word) 48 if old, ok := set[hash]; !ok { 49 set[hash] = word 50 } else { 51 coll++ 52 fmt.Printf( 53 "collision: current word: %s, old word: %s, hash: %d\n", word, old, hash) 54 } 55 } 56 fmt.Printf("encountered %d collisions comparing %d words\n", coll, len(words)) 57 } 58 59 func Test_HashMap_Del(t *testing.T) { 60 hm := NewHashMap(128) 61 for i := 0; i < len(words); i++ { 62 hm.Set(words[i], []byte{0x69}) 63 } 64 util.AssertExpected(t, 25, hm.Len()) 65 count := hm.Len() 66 var stop = hm.Len() 67 for i := 0; i < stop; i++ { 68 ret, ok := hm.Del(words[i]) 69 util.AssertExpected(t, true, ok) 70 util.AssertExpected(t, []byte{0x69}, ret) 71 count-- 72 } 73 util.AssertExpected(t, 0, count) 74 hm.Close() 75 } 76 77 func Test_HashMap_Get(t *testing.T) { 78 hm := NewHashMap(128) 79 for i := 0; i < len(words); i++ { 80 hm.Set(words[i], []byte{0x69}) 81 } 82 util.AssertExpected(t, 25, hm.Len()) 83 var count int 84 for i := 0; i < hm.Len(); i++ { 85 ret, ok := hm.Get(words[i]) 86 util.AssertExpected(t, true, ok) 87 util.AssertExpected(t, []byte{0x69}, ret) 88 count++ 89 } 90 util.AssertExpected(t, 25, count) 91 hm.Close() 92 } 93 94 func Test_HashMap_Len(t *testing.T) { 95 hm := NewHashMap(128) 96 for i := 0; i < len(words); i++ { 97 hm.Set(words[i], []byte{0x69}) 98 } 99 util.AssertExpected(t, 25, hm.Len()) 100 hm.Close() 101 } 102 103 func Test_HashMap_PercentFull(t *testing.T) { 104 hm := NewHashMap(0) 105 for i := 0; i < len(words); i++ { 106 hm.Set(words[i], []byte{0x69}) 107 } 108 percent := fmt.Sprintf("%.2f", hm.PercentFull()) 109 util.AssertExpected(t, "0.78", percent) 110 hm.Close() 111 } 112 113 func Test_HashMap_Set(t *testing.T) { 114 hm := NewHashMap(128) 115 for i := 0; i < len(words); i++ { 116 hm.Set(words[i], []byte{0x69}) 117 } 118 util.AssertExpected(t, 25, hm.Len()) 119 hm.Close() 120 } 121 122 func Test_HashMap_Range(t *testing.T) { 123 hm := NewHashMap(128) 124 for i := 0; i < len(words); i++ { 125 hm.Set(words[i], []byte{0x69}) 126 } 127 util.AssertExpected(t, 25, hm.Len()) 128 var counted int 129 hm.Range(func(key string, value []byte) bool { 130 if key != "" && bytes.Equal(value, []byte{0x69}) { 131 counted++ 132 return true 133 } 134 return false 135 }) 136 util.AssertExpected(t, 25, counted) 137 hm.Close() 138 } 139 140 var result interface{} 141 142 func BenchmarkHashMap_Set1(b *testing.B) { 143 hm := NewHashMap(128) 144 145 b.ResetTimer() 146 b.ReportAllocs() 147 148 var v []byte 149 for n := 0; n < b.N; n++ { 150 // try to get key/value "foo" 151 v, ok := hm.Get("foo") 152 if !ok { 153 // if it doesn't exist, then initialize it 154 hm.Set("foo", make([]byte, 32)) 155 } else { 156 // if it does exist, then pick a random number between 157 // 0 and 256--this will be our bit we try and set 158 ri := uint(rand.Intn(128)) 159 if ok := bits.RawBytesHasBit(&v, ri); !ok { 160 // we check the bit to see if it's already set, and 161 // then we go ahead and set it if it is not set 162 bits.RawBytesSetBit(&v, ri) 163 } 164 // after this, we make sure to save the bitset back to the hashmap 165 if n < 64 { 166 fmt.Printf("addr: %p, %+v\n", v, v) 167 //PrintBits(v) 168 } 169 hm.Set("foo", v) 170 } 171 } 172 result = v 173 } 174 175 func BenchmarkHashMap_Set2(b *testing.B) { 176 hm := NewHashMap(128) 177 178 b.ResetTimer() 179 b.ReportAllocs() 180 181 var v []byte 182 for n := 0; n < b.N; n++ { 183 // try to get key/value "foo" 184 v, ok := hm.Get("foo") 185 if !ok { 186 // if it doesn't exist, then initialize it 187 hm.Set("foo", make([]byte, 32)) 188 } else { 189 v = append(v, []byte{byte(n >> 8)}...) 190 // after this, we make sure to save the bitset back to the hashmap 191 if n < 64 { 192 fmt.Printf("addr: %p, %+v\n", v, v) 193 //PrintBits(v) 194 } 195 hm.Set("foo", v) 196 } 197 } 198 result = v 199 } 200 201 func TestHashMapMillionEntriesSize(t *testing.T) { 202 count := 1000000 203 hm := NewHashMap(512) 204 for i := 0; i < count; i++ { 205 _, ok := hm.Set(strconv.Itoa(i), nil) 206 if ok { 207 t.Errorf("error: could not located value for key: %q\n", strconv.Itoa(i)) 208 } 209 } 210 if hm.Len() != count { 211 t.Errorf("error: incorrect count of entries\n") 212 } 213 fmt.Printf("hashmap containing %d entries is taking %d bytes (%.2f kb, %.2f mb)\n", 214 count, util.Sizeof(hm), float64(util.Sizeof(hm)/1024), float64(util.Sizeof(hm)/1024/1024)) 215 for i := 0; i < count; i++ { 216 _, ok := hm.Get(strconv.Itoa(i)) 217 if !ok { 218 t.Errorf("error: could not located value for key: %q\n", strconv.Itoa(i)) 219 } 220 } 221 for i := 0; i < count; i++ { 222 _, ok := hm.Del(strconv.Itoa(i)) 223 if !ok { 224 t.Errorf("error: could not remove value for key: %q\n", strconv.Itoa(i)) 225 } 226 } 227 if hm.Len() != count-count { 228 t.Errorf("error: incorrect count of entries\n") 229 } 230 hm.Close() 231 }