github.com/moontrade/unsafe@v0.9.1/memory/hash/hash_test.go (about) 1 package hash 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "hash/crc32" 7 "hash/crc64" 8 "math/rand" 9 "testing" 10 "time" 11 ) 12 13 func print_hash(s string) { 14 fmt.Printf("%s: %d\n", s, String(s)) 15 } 16 17 func TestMul64(t *testing.T) { 18 print_hash("h") 19 print_hash("he") 20 print_hash("hel") 21 print_hash("hell") 22 print_hash("hello") 23 print_hash("hellonow") 24 print_hash("hellonowhellonow") 25 print_hash("hellonowhellonowhellonowhellonow") 26 print_hash("hellonowhellonowhellonowhellonowhellonowhellonowhellonowhellonow") 27 28 //println(U64(10)) 29 //println(U64(11)) 30 //println(wymum(5000000000, 11)) 31 //SetSeed(uint64(time.Now().UnixNano())) 32 //fmt.Println(Next()) 33 //for i := 0; i < 10; i++ { 34 // fmt.Println(NextFloat()) 35 //} 36 //fmt.Println(NextGaussian()) 37 //fmt.Println(wymum(10, 11), wymum2(10, 11)) 38 //fmt.Println(wymum(192923, 9877732), wymum2(192923, 9877732)) 39 //fmt.Println(1 ^ uint64(0xe7037ed1a0b428db)) 40 //fmt.Println(99 ^ uint64(0xe7037ed1a0b428db)) 41 //fmt.Println(HashString("hel")) 42 //fmt.Println(HashString("hell")) 43 //fmt.Println(HashString("hello")) 44 //fmt.Println(HashString("hello there today ok")) 45 //fmt.Println(String("hello there today ok hello there today ok hello there today ok o hello there today ok hello there today ok hello there today ok o")) 46 //fmt.Println(HashString("hello")) 47 //fmt.Println(HashString("hello123")) 48 //fmt.Println(uint64(10) >> 2) 49 } 50 51 func TestHashCollisions(t *testing.T) { 52 var ( 53 //c32 int 54 //a32 int 55 //c16 int 56 fn int 57 wyf3 int 58 wyf3string3 int 59 wyf3string4 int 60 wyf3string5 int 61 wyf3string8 int 62 wyf3string20 int 63 wyf3string32 int 64 wyf3string64 int 65 total int 66 ) 67 68 type config struct { 69 low int 70 high int 71 adder int 72 factor float64 73 addressStart int 74 multiplierLow int 75 multiplierHigh int 76 multiplierAdd int 77 } 78 for _, cfg := range []config{ 79 //{2, 10, 4, 8, 65580, 64, 4096, 128}, 80 // WASM like pointer values 81 {40, 1024, 88, 3, 65580, 512, 256000, 96}, 82 {1024, 4096, 512, 3, 65580, 56, 52050, 512}, 83 } { 84 for i := cfg.low; i < cfg.high; i += cfg.adder { 85 var ( 86 entries = i 87 slots = int(float64(i) * cfg.factor) 88 ) 89 for multiplier := cfg.multiplierLow; multiplier < cfg.multiplierHigh; multiplier += cfg.multiplierAdd { 90 total += entries 91 //c32 += testCollisions(entries, multiplier, slots, crc32h) 92 //c16 += testCollisions(entries, multiplier, slots, crc16a) 93 fn += testCollisions(entries, multiplier, slots, FNV32) 94 wyf3 += testCollisions64(entries, multiplier, slots, U64) 95 96 wyf3string3 += testCollisionsString(entries, 3, slots, String) 97 wyf3string4 += testCollisionsString(entries, 4, slots, String) 98 wyf3string5 += testCollisionsString(entries, 5, slots, String) 99 wyf3string8 += testCollisionsString(entries, 8, slots, String) 100 wyf3string20 += testCollisionsString(entries, 20, slots, String) 101 wyf3string32 += testCollisionsString(entries, 32, slots, String) 102 wyf3string64 += testCollisionsString(entries, 64, slots, String) 103 } 104 } 105 } 106 107 println("") 108 println("total ", total) 109 //println("\tcrc32 ", c32) 110 //println("\tcrc16 ", c16) 111 println("\tfnv ", fn) 112 println("\tWYF3 ", wyf3) 113 println("\tWYF3Str 3 ", wyf3string3) 114 println("\tWYF3Str 4 ", wyf3string4) 115 println("\tWYF3Str 5 ", wyf3string5) 116 println("\tWYF3Str 8 ", wyf3string8) 117 println("\tWYF3Str 20 ", wyf3string20) 118 println("\tWYF3Str 32 ", wyf3string32) 119 println("\tWYF3Str 64 ", wyf3string64) 120 } 121 122 func rangeRandom(min, max uint32) uint32 { 123 return uint32(rand.Int31n(int32(max-min)) + int32(min)) 124 } 125 126 func testCollisions(entries, multiplier, slots int, hasher func(uint32) uint32) int { 127 m := make(map[uint32]struct{}) 128 count := 0 129 130 ptr := 65680 131 132 for i := 0; i < entries; i++ { 133 v := hasher(uint32(ptr)) 134 ptr += multiplier 135 index := v % uint32(slots) 136 137 _, ok := m[index] 138 if ok { 139 count++ 140 } else { 141 m[index] = struct{}{} 142 } 143 } 144 return count 145 } 146 147 var seededRand = rand.New( 148 rand.NewSource(time.Now().UnixNano())) 149 150 func StringWithCharset(length int, charset string) string { 151 b := make([]byte, length) 152 for i := range b { 153 b[i] = charset[seededRand.Intn(len(charset))] 154 } 155 return string(b) 156 } 157 158 const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 159 160 func testCollisionsString(entries, size, slots int, hasher func(b string) uint64) int { 161 m := make(map[uint64]struct{}) 162 count := 0 163 164 for i := 0; i < entries; i++ { 165 s := StringWithCharset(size, charset) 166 v := hasher(s) 167 index := v % uint64(slots) 168 169 _, ok := m[index] 170 if ok { 171 count++ 172 } else { 173 m[index] = struct{}{} 174 } 175 } 176 return count 177 } 178 179 func testCollisions64(entries, multiplier, slots int, hasher func(uint64) uint64) int { 180 m := make(map[uint64]struct{}) 181 count := 0 182 183 ptr := 65536 184 185 for i := uint64(0); i < uint64(entries); i++ { 186 v := hasher(uint64(ptr)) 187 ptr += multiplier 188 index := v % uint64(slots) 189 190 _, ok := m[index] 191 if ok { 192 count++ 193 } else { 194 m[index] = struct{}{} 195 } 196 } 197 return count 198 } 199 200 func crc64h(v uint32) uint32 { 201 h := crc64.New(crc64.MakeTable(crc64.ECMA)) 202 h.Reset() 203 b := [4]byte{} 204 binary.LittleEndian.PutUint32(b[0:], v) 205 h.Write(b[0:4]) 206 return uint32(h.Sum64()) 207 } 208 209 func crc32h(v uint32) uint32 { 210 h := crc32.NewIEEE() 211 h.Reset() 212 b := [4]byte{} 213 binary.LittleEndian.PutUint32(b[0:], v) 214 h.Write(b[0:4]) 215 return h.Sum32() 216 } 217 218 var crc16tab = [256]uint16{ 219 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 220 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 221 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 222 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 223 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 224 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 225 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 226 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 227 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 228 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 229 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 230 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 231 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 232 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 233 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 234 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 235 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 236 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 237 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 238 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 239 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 240 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 241 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 242 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 243 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 244 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 245 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 246 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 247 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 248 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 249 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 250 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0} 251 252 func crc16a(v uint32) uint32 { 253 crc := uint16(0) 254 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v))] 255 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<8))] 256 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<16))] 257 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<24))] 258 return uint32(crc) 259 } 260 261 func BenchmarkHash(b *testing.B) { 262 const multiply = uint64(1) 263 seed := rand.Uint64() 264 265 //FNV64(FNV64((11 + 1) * seed)) 266 String(StringWithCharset(128, charset)) 267 String(StringWithCharset(3, charset)) 268 String(StringWithCharset(4, charset)) 269 String(StringWithCharset(16, charset)) 270 String(StringWithCharset(32, charset)) 271 String(StringWithCharset(51, charset)) 272 String(StringWithCharset(64, charset)) 273 String(StringWithCharset(96, charset)) 274 String(StringWithCharset(128, charset)) 275 String(StringWithCharset(256, charset)) 276 U64(U64((11 + 1) * seed)) 277 278 //b.Run("crc32", func(b *testing.B) { 279 // for i := 0; i < b.N; i++ { 280 // crc32h(23) 281 // } 282 //}) 283 //b.Run("crc16", func(b *testing.B) { 284 // for i := 0; i < b.N; i++ { 285 // crc16a(23) 286 // } 287 //}) 288 //b.Run("crc16", func(b *testing.B) { 289 // for i := 0; i < b.N; i++ { 290 // crc16a(23) 291 // } 292 //}) 293 //b.Run("FNV64a", func(b *testing.B) { 294 // for i := uint64(0); i < uint64(b.N)*multiply; i++ { 295 // FNV32a(uint32((i + 1) * seed)) 296 // } 297 //}) 298 b.Run("Hash U64", func(b *testing.B) { 299 b.ResetTimer() 300 for i := 0; i < b.N; i++ { 301 U64(uint64(i + 1)) 302 } 303 }) 304 b.Run("Hash 3", func(b *testing.B) { 305 str := "hel" 306 307 b.ResetTimer() 308 for i := 0; i < b.N; i++ { 309 String(str) 310 } 311 }) 312 b.Run("Hash 5", func(b *testing.B) { 313 str := "hello" 314 315 b.ResetTimer() 316 for i := 0; i < b.N; i++ { 317 String(str) 318 } 319 }) 320 b.Run("Hash 8", func(b *testing.B) { 321 str := "hellobye" 322 323 b.ResetTimer() 324 for i := 0; i < b.N; i++ { 325 String(str) 326 } 327 }) 328 b.Run("Hash 16", func(b *testing.B) { 329 str := "hellobyehellobye" 330 331 b.ResetTimer() 332 for i := 0; i < b.N; i++ { 333 String(str) 334 } 335 }) 336 b.Run("Hash 32", func(b *testing.B) { 337 str := "hellobyehellobyehellobyehellobye" 338 339 b.ResetTimer() 340 for i := 0; i < b.N; i++ { 341 String(str) 342 } 343 }) 344 b.Run("Hash 64", func(b *testing.B) { 345 str := "hellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobye" 346 347 b.ResetTimer() 348 for i := 0; i < b.N; i++ { 349 String(str) 350 } 351 }) 352 b.Run("Hash 128", func(b *testing.B) { 353 str := "hellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobye" 354 355 b.ResetTimer() 356 for i := 0; i < b.N; i++ { 357 String(str) 358 } 359 }) 360 b.Run("Hash 129", func(b *testing.B) { 361 str := "hello there today ok hello there today ok hello there today ok o hello there today ok hello there today ok hello there today ok o" 362 363 b.ResetTimer() 364 for i := 0; i < b.N; i++ { 365 String(str) 366 } 367 }) 368 b.Run("Hash 256", func(b *testing.B) { 369 str := "hellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobyehellobye" 370 371 b.ResetTimer() 372 for i := 0; i < b.N; i++ { 373 String(str) 374 } 375 }) 376 }