github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/hash_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "fmt" 9 "math" 10 "math/rand" 11 "reflect" 12 . "runtime" 13 "strings" 14 "testing" 15 "unsafe" 16 ) 17 18 func TestMemHash32Equality(t *testing.T) { 19 if *UseAeshash { 20 t.Skip("skipping since AES hash implementation is used") 21 } 22 var b [4]byte 23 r := rand.New(rand.NewSource(1234)) 24 seed := uintptr(r.Uint64()) 25 for i := 0; i < 100; i++ { 26 randBytes(r, b[:]) 27 got := MemHash32(unsafe.Pointer(&b), seed) 28 want := MemHash(unsafe.Pointer(&b), seed, 4) 29 if got != want { 30 t.Errorf("MemHash32(%x, %v) = %v; want %v", b, seed, got, want) 31 } 32 } 33 } 34 35 func TestMemHash64Equality(t *testing.T) { 36 if *UseAeshash { 37 t.Skip("skipping since AES hash implementation is used") 38 } 39 var b [8]byte 40 r := rand.New(rand.NewSource(1234)) 41 seed := uintptr(r.Uint64()) 42 for i := 0; i < 100; i++ { 43 randBytes(r, b[:]) 44 got := MemHash64(unsafe.Pointer(&b), seed) 45 want := MemHash(unsafe.Pointer(&b), seed, 8) 46 if got != want { 47 t.Errorf("MemHash64(%x, %v) = %v; want %v", b, seed, got, want) 48 } 49 } 50 } 51 52 func TestCompilerVsRuntimeHash(t *testing.T) { 53 // Test to make sure the compiler's hash function and the runtime's hash function agree. 54 // See issue 37716. 55 for _, m := range []interface{}{ 56 map[bool]int{}, 57 map[int8]int{}, 58 map[uint8]int{}, 59 map[int16]int{}, 60 map[uint16]int{}, 61 map[int32]int{}, 62 map[uint32]int{}, 63 map[int64]int{}, 64 map[uint64]int{}, 65 map[int]int{}, 66 map[uint]int{}, 67 map[uintptr]int{}, 68 map[*byte]int{}, 69 map[chan int]int{}, 70 map[unsafe.Pointer]int{}, 71 map[float32]int{}, 72 map[float64]int{}, 73 map[complex64]int{}, 74 map[complex128]int{}, 75 map[string]int{}, 76 //map[interface{}]int{}, 77 //map[interface{F()}]int{}, 78 map[[8]uint64]int{}, 79 map[[8]string]int{}, 80 map[struct{ a, b, c, d int32 }]int{}, // Note: tests AMEM128 81 map[struct{ a, b, _, d int32 }]int{}, 82 map[struct { 83 a, b int32 84 c float32 85 d, e [8]byte 86 }]int{}, 87 map[struct { 88 a int16 89 b int64 90 }]int{}, 91 } { 92 k := reflect.New(reflect.TypeOf(m).Key()).Elem().Interface() // the zero key 93 x, y := MapHashCheck(m, k) 94 if x != y { 95 t.Errorf("hashes did not match (%x vs %x) for map %T", x, y, m) 96 } 97 } 98 } 99 100 // Smhasher is a torture test for hash functions. 101 // https://code.google.com/p/smhasher/ 102 // This code is a port of some of the Smhasher tests to Go. 103 // 104 // The current AES hash function passes Smhasher. Our fallback 105 // hash functions don't, so we only enable the difficult tests when 106 // we know the AES implementation is available. 107 108 // Sanity checks. 109 // hash should not depend on values outside key. 110 // hash should not depend on alignment. 111 func TestSmhasherSanity(t *testing.T) { 112 r := rand.New(rand.NewSource(1234)) 113 const REP = 10 114 const KEYMAX = 128 115 const PAD = 16 116 const OFFMAX = 16 117 for k := 0; k < REP; k++ { 118 for n := 0; n < KEYMAX; n++ { 119 for i := 0; i < OFFMAX; i++ { 120 var b [KEYMAX + OFFMAX + 2*PAD]byte 121 var c [KEYMAX + OFFMAX + 2*PAD]byte 122 randBytes(r, b[:]) 123 randBytes(r, c[:]) 124 copy(c[PAD+i:PAD+i+n], b[PAD:PAD+n]) 125 if BytesHash(b[PAD:PAD+n], 0) != BytesHash(c[PAD+i:PAD+i+n], 0) { 126 t.Errorf("hash depends on bytes outside key") 127 } 128 } 129 } 130 } 131 } 132 133 type HashSet struct { 134 m map[uintptr]struct{} // set of hashes added 135 n int // number of hashes added 136 } 137 138 func newHashSet() *HashSet { 139 return &HashSet{make(map[uintptr]struct{}), 0} 140 } 141 func (s *HashSet) add(h uintptr) { 142 s.m[h] = struct{}{} 143 s.n++ 144 } 145 func (s *HashSet) addS(x string) { 146 s.add(StringHash(x, 0)) 147 } 148 func (s *HashSet) addB(x []byte) { 149 s.add(BytesHash(x, 0)) 150 } 151 func (s *HashSet) addS_seed(x string, seed uintptr) { 152 s.add(StringHash(x, seed)) 153 } 154 func (s *HashSet) check(t *testing.T) { 155 const SLOP = 50.0 156 collisions := s.n - len(s.m) 157 pairs := int64(s.n) * int64(s.n-1) / 2 158 expected := float64(pairs) / math.Pow(2.0, float64(hashSize)) 159 stddev := math.Sqrt(expected) 160 if float64(collisions) > expected+SLOP*(3*stddev+1) { 161 t.Errorf("unexpected number of collisions: got=%d mean=%f stddev=%f threshold=%f", collisions, expected, stddev, expected+SLOP*(3*stddev+1)) 162 } 163 } 164 165 // a string plus adding zeros must make distinct hashes 166 func TestSmhasherAppendedZeros(t *testing.T) { 167 s := "hello" + strings.Repeat("\x00", 256) 168 h := newHashSet() 169 for i := 0; i <= len(s); i++ { 170 h.addS(s[:i]) 171 } 172 h.check(t) 173 } 174 175 // All 0-3 byte strings have distinct hashes. 176 func TestSmhasherSmallKeys(t *testing.T) { 177 h := newHashSet() 178 var b [3]byte 179 for i := 0; i < 256; i++ { 180 b[0] = byte(i) 181 h.addB(b[:1]) 182 for j := 0; j < 256; j++ { 183 b[1] = byte(j) 184 h.addB(b[:2]) 185 if !testing.Short() { 186 for k := 0; k < 256; k++ { 187 b[2] = byte(k) 188 h.addB(b[:3]) 189 } 190 } 191 } 192 } 193 h.check(t) 194 } 195 196 // Different length strings of all zeros have distinct hashes. 197 func TestSmhasherZeros(t *testing.T) { 198 N := 256 * 1024 199 if testing.Short() { 200 N = 1024 201 } 202 h := newHashSet() 203 b := make([]byte, N) 204 for i := 0; i <= N; i++ { 205 h.addB(b[:i]) 206 } 207 h.check(t) 208 } 209 210 // Strings with up to two nonzero bytes all have distinct hashes. 211 func TestSmhasherTwoNonzero(t *testing.T) { 212 if GOARCH == "wasm" { 213 t.Skip("Too slow on wasm") 214 } 215 if testing.Short() { 216 t.Skip("Skipping in short mode") 217 } 218 h := newHashSet() 219 for n := 2; n <= 16; n++ { 220 twoNonZero(h, n) 221 } 222 h.check(t) 223 } 224 func twoNonZero(h *HashSet, n int) { 225 b := make([]byte, n) 226 227 // all zero 228 h.addB(b) 229 230 // one non-zero byte 231 for i := 0; i < n; i++ { 232 for x := 1; x < 256; x++ { 233 b[i] = byte(x) 234 h.addB(b) 235 b[i] = 0 236 } 237 } 238 239 // two non-zero bytes 240 for i := 0; i < n; i++ { 241 for x := 1; x < 256; x++ { 242 b[i] = byte(x) 243 for j := i + 1; j < n; j++ { 244 for y := 1; y < 256; y++ { 245 b[j] = byte(y) 246 h.addB(b) 247 b[j] = 0 248 } 249 } 250 b[i] = 0 251 } 252 } 253 } 254 255 // Test strings with repeats, like "abcdabcdabcdabcd..." 256 func TestSmhasherCyclic(t *testing.T) { 257 if testing.Short() { 258 t.Skip("Skipping in short mode") 259 } 260 r := rand.New(rand.NewSource(1234)) 261 const REPEAT = 8 262 const N = 1000000 263 for n := 4; n <= 12; n++ { 264 h := newHashSet() 265 b := make([]byte, REPEAT*n) 266 for i := 0; i < N; i++ { 267 b[0] = byte(i * 79 % 97) 268 b[1] = byte(i * 43 % 137) 269 b[2] = byte(i * 151 % 197) 270 b[3] = byte(i * 199 % 251) 271 randBytes(r, b[4:n]) 272 for j := n; j < n*REPEAT; j++ { 273 b[j] = b[j-n] 274 } 275 h.addB(b) 276 } 277 h.check(t) 278 } 279 } 280 281 // Test strings with only a few bits set 282 func TestSmhasherSparse(t *testing.T) { 283 if GOARCH == "wasm" { 284 t.Skip("Too slow on wasm") 285 } 286 if testing.Short() { 287 t.Skip("Skipping in short mode") 288 } 289 sparse(t, 32, 6) 290 sparse(t, 40, 6) 291 sparse(t, 48, 5) 292 sparse(t, 56, 5) 293 sparse(t, 64, 5) 294 sparse(t, 96, 4) 295 sparse(t, 256, 3) 296 sparse(t, 2048, 2) 297 } 298 func sparse(t *testing.T, n int, k int) { 299 b := make([]byte, n/8) 300 h := newHashSet() 301 setbits(h, b, 0, k) 302 h.check(t) 303 } 304 305 // set up to k bits at index i and greater 306 func setbits(h *HashSet, b []byte, i int, k int) { 307 h.addB(b) 308 if k == 0 { 309 return 310 } 311 for j := i; j < len(b)*8; j++ { 312 b[j/8] |= byte(1 << uint(j&7)) 313 setbits(h, b, j+1, k-1) 314 b[j/8] &= byte(^(1 << uint(j&7))) 315 } 316 } 317 318 // Test all possible combinations of n blocks from the set s. 319 // "permutation" is a bad name here, but it is what Smhasher uses. 320 func TestSmhasherPermutation(t *testing.T) { 321 if GOARCH == "wasm" { 322 t.Skip("Too slow on wasm") 323 } 324 if testing.Short() { 325 t.Skip("Skipping in short mode") 326 } 327 permutation(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7}, 8) 328 permutation(t, []uint32{0, 1 << 29, 2 << 29, 3 << 29, 4 << 29, 5 << 29, 6 << 29, 7 << 29}, 8) 329 permutation(t, []uint32{0, 1}, 20) 330 permutation(t, []uint32{0, 1 << 31}, 20) 331 permutation(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 1 << 29, 2 << 29, 3 << 29, 4 << 29, 5 << 29, 6 << 29, 7 << 29}, 6) 332 } 333 func permutation(t *testing.T, s []uint32, n int) { 334 b := make([]byte, n*4) 335 h := newHashSet() 336 genPerm(h, b, s, 0) 337 h.check(t) 338 } 339 func genPerm(h *HashSet, b []byte, s []uint32, n int) { 340 h.addB(b[:n]) 341 if n == len(b) { 342 return 343 } 344 for _, v := range s { 345 b[n] = byte(v) 346 b[n+1] = byte(v >> 8) 347 b[n+2] = byte(v >> 16) 348 b[n+3] = byte(v >> 24) 349 genPerm(h, b, s, n+4) 350 } 351 } 352 353 type Key interface { 354 clear() // set bits all to 0 355 random(r *rand.Rand) // set key to something random 356 bits() int // how many bits key has 357 flipBit(i int) // flip bit i of the key 358 hash() uintptr // hash the key 359 name() string // for error reporting 360 } 361 362 type BytesKey struct { 363 b []byte 364 } 365 366 func (k *BytesKey) clear() { 367 for i := range k.b { 368 k.b[i] = 0 369 } 370 } 371 func (k *BytesKey) random(r *rand.Rand) { 372 randBytes(r, k.b) 373 } 374 func (k *BytesKey) bits() int { 375 return len(k.b) * 8 376 } 377 func (k *BytesKey) flipBit(i int) { 378 k.b[i>>3] ^= byte(1 << uint(i&7)) 379 } 380 func (k *BytesKey) hash() uintptr { 381 return BytesHash(k.b, 0) 382 } 383 func (k *BytesKey) name() string { 384 return fmt.Sprintf("bytes%d", len(k.b)) 385 } 386 387 type Int32Key struct { 388 i uint32 389 } 390 391 func (k *Int32Key) clear() { 392 k.i = 0 393 } 394 func (k *Int32Key) random(r *rand.Rand) { 395 k.i = r.Uint32() 396 } 397 func (k *Int32Key) bits() int { 398 return 32 399 } 400 func (k *Int32Key) flipBit(i int) { 401 k.i ^= 1 << uint(i) 402 } 403 func (k *Int32Key) hash() uintptr { 404 return Int32Hash(k.i, 0) 405 } 406 func (k *Int32Key) name() string { 407 return "int32" 408 } 409 410 type Int64Key struct { 411 i uint64 412 } 413 414 func (k *Int64Key) clear() { 415 k.i = 0 416 } 417 func (k *Int64Key) random(r *rand.Rand) { 418 k.i = uint64(r.Uint32()) + uint64(r.Uint32())<<32 419 } 420 func (k *Int64Key) bits() int { 421 return 64 422 } 423 func (k *Int64Key) flipBit(i int) { 424 k.i ^= 1 << uint(i) 425 } 426 func (k *Int64Key) hash() uintptr { 427 return Int64Hash(k.i, 0) 428 } 429 func (k *Int64Key) name() string { 430 return "int64" 431 } 432 433 type EfaceKey struct { 434 i interface{} 435 } 436 437 func (k *EfaceKey) clear() { 438 k.i = nil 439 } 440 func (k *EfaceKey) random(r *rand.Rand) { 441 k.i = uint64(r.Int63()) 442 } 443 func (k *EfaceKey) bits() int { 444 // use 64 bits. This tests inlined interfaces 445 // on 64-bit targets and indirect interfaces on 446 // 32-bit targets. 447 return 64 448 } 449 func (k *EfaceKey) flipBit(i int) { 450 k.i = k.i.(uint64) ^ uint64(1)<<uint(i) 451 } 452 func (k *EfaceKey) hash() uintptr { 453 return EfaceHash(k.i, 0) 454 } 455 func (k *EfaceKey) name() string { 456 return "Eface" 457 } 458 459 type IfaceKey struct { 460 i interface { 461 F() 462 } 463 } 464 type fInter uint64 465 466 func (x fInter) F() { 467 } 468 469 func (k *IfaceKey) clear() { 470 k.i = nil 471 } 472 func (k *IfaceKey) random(r *rand.Rand) { 473 k.i = fInter(r.Int63()) 474 } 475 func (k *IfaceKey) bits() int { 476 // use 64 bits. This tests inlined interfaces 477 // on 64-bit targets and indirect interfaces on 478 // 32-bit targets. 479 return 64 480 } 481 func (k *IfaceKey) flipBit(i int) { 482 k.i = k.i.(fInter) ^ fInter(1)<<uint(i) 483 } 484 func (k *IfaceKey) hash() uintptr { 485 return IfaceHash(k.i, 0) 486 } 487 func (k *IfaceKey) name() string { 488 return "Iface" 489 } 490 491 // Flipping a single bit of a key should flip each output bit with 50% probability. 492 func TestSmhasherAvalanche(t *testing.T) { 493 if GOARCH == "wasm" { 494 t.Skip("Too slow on wasm") 495 } 496 if testing.Short() { 497 t.Skip("Skipping in short mode") 498 } 499 avalancheTest1(t, &BytesKey{make([]byte, 2)}) 500 avalancheTest1(t, &BytesKey{make([]byte, 4)}) 501 avalancheTest1(t, &BytesKey{make([]byte, 8)}) 502 avalancheTest1(t, &BytesKey{make([]byte, 16)}) 503 avalancheTest1(t, &BytesKey{make([]byte, 32)}) 504 avalancheTest1(t, &BytesKey{make([]byte, 200)}) 505 avalancheTest1(t, &Int32Key{}) 506 avalancheTest1(t, &Int64Key{}) 507 avalancheTest1(t, &EfaceKey{}) 508 avalancheTest1(t, &IfaceKey{}) 509 } 510 func avalancheTest1(t *testing.T, k Key) { 511 const REP = 100000 512 r := rand.New(rand.NewSource(1234)) 513 n := k.bits() 514 515 // grid[i][j] is a count of whether flipping 516 // input bit i affects output bit j. 517 grid := make([][hashSize]int, n) 518 519 for z := 0; z < REP; z++ { 520 // pick a random key, hash it 521 k.random(r) 522 h := k.hash() 523 524 // flip each bit, hash & compare the results 525 for i := 0; i < n; i++ { 526 k.flipBit(i) 527 d := h ^ k.hash() 528 k.flipBit(i) 529 530 // record the effects of that bit flip 531 g := &grid[i] 532 for j := 0; j < hashSize; j++ { 533 g[j] += int(d & 1) 534 d >>= 1 535 } 536 } 537 } 538 539 // Each entry in the grid should be about REP/2. 540 // More precisely, we did N = k.bits() * hashSize experiments where 541 // each is the sum of REP coin flips. We want to find bounds on the 542 // sum of coin flips such that a truly random experiment would have 543 // all sums inside those bounds with 99% probability. 544 N := n * hashSize 545 var c float64 546 // find c such that Prob(mean-c*stddev < x < mean+c*stddev)^N > .9999 547 for c = 0.0; math.Pow(math.Erf(c/math.Sqrt(2)), float64(N)) < .9999; c += .1 { 548 } 549 c *= 4.0 // allowed slack - we don't need to be perfectly random 550 mean := .5 * REP 551 stddev := .5 * math.Sqrt(REP) 552 low := int(mean - c*stddev) 553 high := int(mean + c*stddev) 554 for i := 0; i < n; i++ { 555 for j := 0; j < hashSize; j++ { 556 x := grid[i][j] 557 if x < low || x > high { 558 t.Errorf("bad bias for %s bit %d -> bit %d: %d/%d\n", k.name(), i, j, x, REP) 559 } 560 } 561 } 562 } 563 564 // All bit rotations of a set of distinct keys 565 func TestSmhasherWindowed(t *testing.T) { 566 t.Logf("32 bit keys") 567 windowed(t, &Int32Key{}) 568 t.Logf("64 bit keys") 569 windowed(t, &Int64Key{}) 570 t.Logf("string keys") 571 windowed(t, &BytesKey{make([]byte, 128)}) 572 } 573 func windowed(t *testing.T, k Key) { 574 if GOARCH == "wasm" { 575 t.Skip("Too slow on wasm") 576 } 577 if testing.Short() { 578 t.Skip("Skipping in short mode") 579 } 580 const BITS = 16 581 582 for r := 0; r < k.bits(); r++ { 583 h := newHashSet() 584 for i := 0; i < 1<<BITS; i++ { 585 k.clear() 586 for j := 0; j < BITS; j++ { 587 if i>>uint(j)&1 != 0 { 588 k.flipBit((j + r) % k.bits()) 589 } 590 } 591 h.add(k.hash()) 592 } 593 h.check(t) 594 } 595 } 596 597 // All keys of the form prefix + [A-Za-z0-9]*N + suffix. 598 func TestSmhasherText(t *testing.T) { 599 if testing.Short() { 600 t.Skip("Skipping in short mode") 601 } 602 text(t, "Foo", "Bar") 603 text(t, "FooBar", "") 604 text(t, "", "FooBar") 605 } 606 func text(t *testing.T, prefix, suffix string) { 607 const N = 4 608 const S = "ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789" 609 const L = len(S) 610 b := make([]byte, len(prefix)+N+len(suffix)) 611 copy(b, prefix) 612 copy(b[len(prefix)+N:], suffix) 613 h := newHashSet() 614 c := b[len(prefix):] 615 for i := 0; i < L; i++ { 616 c[0] = S[i] 617 for j := 0; j < L; j++ { 618 c[1] = S[j] 619 for k := 0; k < L; k++ { 620 c[2] = S[k] 621 for x := 0; x < L; x++ { 622 c[3] = S[x] 623 h.addB(b) 624 } 625 } 626 } 627 } 628 h.check(t) 629 } 630 631 // Make sure different seed values generate different hashes. 632 func TestSmhasherSeed(t *testing.T) { 633 h := newHashSet() 634 const N = 100000 635 s := "hello" 636 for i := 0; i < N; i++ { 637 h.addS_seed(s, uintptr(i)) 638 } 639 h.check(t) 640 } 641 642 // size of the hash output (32 or 64 bits) 643 const hashSize = 32 + int(^uintptr(0)>>63<<5) 644 645 func randBytes(r *rand.Rand, b []byte) { 646 for i := range b { 647 b[i] = byte(r.Uint32()) 648 } 649 } 650 651 func benchmarkHash(b *testing.B, n int) { 652 s := strings.Repeat("A", n) 653 654 for i := 0; i < b.N; i++ { 655 StringHash(s, 0) 656 } 657 b.SetBytes(int64(n)) 658 } 659 660 func BenchmarkHash5(b *testing.B) { benchmarkHash(b, 5) } 661 func BenchmarkHash16(b *testing.B) { benchmarkHash(b, 16) } 662 func BenchmarkHash64(b *testing.B) { benchmarkHash(b, 64) } 663 func BenchmarkHash1024(b *testing.B) { benchmarkHash(b, 1024) } 664 func BenchmarkHash65536(b *testing.B) { benchmarkHash(b, 65536) } 665 666 func TestArrayHash(t *testing.T) { 667 // Make sure that "" in arrays hash correctly. The hash 668 // should at least scramble the input seed so that, e.g., 669 // {"","foo"} and {"foo",""} have different hashes. 670 671 // If the hash is bad, then all (8 choose 4) = 70 keys 672 // have the same hash. If so, we allocate 70/8 = 8 673 // overflow buckets. If the hash is good we don't 674 // normally allocate any overflow buckets, and the 675 // probability of even one or two overflows goes down rapidly. 676 // (There is always 1 allocation of the bucket array. The map 677 // header is allocated on the stack.) 678 f := func() { 679 // Make the key type at most 128 bytes. Otherwise, 680 // we get an allocation per key. 681 type key [8]string 682 m := make(map[key]bool, 70) 683 684 // fill m with keys that have 4 "foo"s and 4 ""s. 685 for i := 0; i < 256; i++ { 686 var k key 687 cnt := 0 688 for j := uint(0); j < 8; j++ { 689 if i>>j&1 != 0 { 690 k[j] = "foo" 691 cnt++ 692 } 693 } 694 if cnt == 4 { 695 m[k] = true 696 } 697 } 698 if len(m) != 70 { 699 t.Errorf("bad test: (8 choose 4) should be 70, not %d", len(m)) 700 } 701 } 702 if n := testing.AllocsPerRun(10, f); n > 6 { 703 t.Errorf("too many allocs %f - hash not balanced", n) 704 } 705 } 706 func TestStructHash(t *testing.T) { 707 // See the comment in TestArrayHash. 708 f := func() { 709 type key struct { 710 a, b, c, d, e, f, g, h string 711 } 712 m := make(map[key]bool, 70) 713 714 // fill m with keys that have 4 "foo"s and 4 ""s. 715 for i := 0; i < 256; i++ { 716 var k key 717 cnt := 0 718 if i&1 != 0 { 719 k.a = "foo" 720 cnt++ 721 } 722 if i&2 != 0 { 723 k.b = "foo" 724 cnt++ 725 } 726 if i&4 != 0 { 727 k.c = "foo" 728 cnt++ 729 } 730 if i&8 != 0 { 731 k.d = "foo" 732 cnt++ 733 } 734 if i&16 != 0 { 735 k.e = "foo" 736 cnt++ 737 } 738 if i&32 != 0 { 739 k.f = "foo" 740 cnt++ 741 } 742 if i&64 != 0 { 743 k.g = "foo" 744 cnt++ 745 } 746 if i&128 != 0 { 747 k.h = "foo" 748 cnt++ 749 } 750 if cnt == 4 { 751 m[k] = true 752 } 753 } 754 if len(m) != 70 { 755 t.Errorf("bad test: (8 choose 4) should be 70, not %d", len(m)) 756 } 757 } 758 if n := testing.AllocsPerRun(10, f); n > 6 { 759 t.Errorf("too many allocs %f - hash not balanced", n) 760 } 761 } 762 763 var sink uint64 764 765 func BenchmarkAlignedLoad(b *testing.B) { 766 var buf [16]byte 767 p := unsafe.Pointer(&buf[0]) 768 var s uint64 769 for i := 0; i < b.N; i++ { 770 s += ReadUnaligned64(p) 771 } 772 sink = s 773 } 774 775 func BenchmarkUnalignedLoad(b *testing.B) { 776 var buf [16]byte 777 p := unsafe.Pointer(&buf[1]) 778 var s uint64 779 for i := 0; i < b.N; i++ { 780 s += ReadUnaligned64(p) 781 } 782 sink = s 783 } 784 785 func TestCollisions(t *testing.T) { 786 if testing.Short() { 787 t.Skip("Skipping in short mode") 788 } 789 for i := 0; i < 16; i++ { 790 for j := 0; j < 16; j++ { 791 if j == i { 792 continue 793 } 794 var a [16]byte 795 m := make(map[uint16]struct{}, 1<<16) 796 for n := 0; n < 1<<16; n++ { 797 a[i] = byte(n) 798 a[j] = byte(n >> 8) 799 m[uint16(BytesHash(a[:], 0))] = struct{}{} 800 } 801 if len(m) <= 1<<15 { 802 t.Errorf("too many collisions i=%d j=%d outputs=%d out of 65536\n", i, j, len(m)) 803 } 804 } 805 } 806 }