github.com/fufuok/utils@v1.0.10/xhash/hasher_xsync_test.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package xhash 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "testing" 11 ) 12 13 func TestMakeHashFunc(t *testing.T) { 14 type User struct { 15 Name string 16 City string 17 } 18 19 sHasher := MakeHasher[string]() 20 iHasher := MakeHasher[User]() 21 22 // Not that much to test TBH. 23 // check that hash is not always the same 24 for i := 0; ; i++ { 25 if sHasher("foo") != sHasher("bar") { 26 break 27 } 28 if i >= 100 { 29 t.Error("sHasher is always the same") 30 break 31 } 32 } 33 34 if sHasher("foo") != sHasher("foo") { 35 t.Error("sHasher is not deterministic") 36 } 37 38 if iHasher(User{Name: "Ivan", City: "Sofia"}) != iHasher(User{Name: "Ivan", City: "Sofia"}) { 39 t.Error("iHasher is not deterministic") 40 } 41 } 42 43 func BenchmarkMakeHashFunc(b *testing.B) { 44 type Point struct { 45 X, Y, Z int 46 } 47 48 type User struct { 49 ID int 50 FirstName string 51 LastName string 52 IsActive bool 53 City string 54 } 55 56 type PadInside struct { 57 A int 58 B byte 59 C int 60 } 61 62 type PadTrailing struct { 63 A int 64 B byte 65 } 66 67 doBenchmarkMakeHashFunc(b, int64(116)) 68 doBenchmarkMakeHashFunc(b, int32(116)) 69 doBenchmarkMakeHashFunc(b, 3.14) 70 doBenchmarkMakeHashFunc(b, "test key test key test key test key test key test key test key test key test key ") 71 doBenchmarkMakeHashFunc(b, Point{1, 2, 3}) 72 doBenchmarkMakeHashFunc(b, User{ID: 1, FirstName: "Ivan", LastName: "Ivanov", IsActive: true, City: "Sofia"}) 73 doBenchmarkMakeHashFunc(b, PadInside{}) 74 doBenchmarkMakeHashFunc(b, PadTrailing{}) 75 doBenchmarkMakeHashFunc(b, [1024]byte{}) 76 doBenchmarkMakeHashFunc(b, [128]Point{}) 77 doBenchmarkMakeHashFunc(b, [128]User{}) 78 doBenchmarkMakeHashFunc(b, [128]PadInside{}) 79 doBenchmarkMakeHashFunc(b, [128]PadTrailing{}) 80 } 81 82 func doBenchmarkMakeHashFunc[T comparable](b *testing.B, val T) { 83 hash := MakeHasher[T]() 84 b.Run(fmt.Sprintf("%T", val), func(b *testing.B) { 85 b.ReportAllocs() 86 for i := 0; i < b.N; i++ { 87 _ = hash(val) 88 } 89 }) 90 } 91 92 func TestCollision_MakeHasher(t *testing.T) { 93 n := 20_000_000 94 sHasher := MakeHasher[string]() 95 iHasher := MakeHasher[int]() 96 ms := make(map[uint64]string) 97 mi := make(map[uint64]int) 98 for i := 0; i < n; i++ { 99 s := strconv.Itoa(i) 100 hs := sHasher(s) 101 hi := iHasher(i) 102 if v, ok := ms[hs]; ok { 103 t.Fatalf("Collision: %s(%d) == %s(%d)", v, sHasher(v), s, sHasher(s)) 104 } 105 if v, ok := mi[hi]; ok { 106 t.Fatalf("Collision: %d(%d) == %d(%d)", v, iHasher(v), i, iHasher(i)) 107 } 108 ms[hs] = s 109 mi[hi] = i 110 } 111 112 hi := iHasher(7) 113 if _, ok := mi[hi]; !ok { 114 t.Fatalf("The number 7 should exist") 115 } 116 if len(ms) != len(mi) || len(ms) != n { 117 t.Fatalf("Hash count: %d, %d, %d", len(ms), len(mi), n) 118 } 119 } 120 121 func BenchmarkHasher_MakeHasher(b *testing.B) { 122 sHasher := MakeHasher[string]() 123 iHasher := MakeHasher[int]() 124 b.ReportAllocs() 125 b.ResetTimer() 126 b.Run("string", func(b *testing.B) { 127 for i := 0; i < b.N; i++ { 128 _ = sHasher(strconv.Itoa(i)) 129 } 130 }) 131 b.Run("int", func(b *testing.B) { 132 for i := 0; i < b.N; i++ { 133 _ = iHasher(i) 134 } 135 }) 136 } 137 138 func BenchmarkHasher_Parallel_MakeHasher(b *testing.B) { 139 sHasher := MakeHasher[string]() 140 s := strings.Repeat(testString, 10) 141 b.ReportAllocs() 142 b.ResetTimer() 143 b.RunParallel(func(pb *testing.PB) { 144 for pb.Next() { 145 _ = sHasher(s) 146 } 147 }) 148 } 149 150 // go test -run=^$ -benchmem -count=2 -bench=BenchmarkHasher 151 // goos: linux 152 // goarch: amd64 153 // pkg: github.com/fufuok/utils/xhash 154 // cpu: AMD Ryzen 7 5700G with Radeon Graphics 155 // BenchmarkHasher_MakeHasher/string-16 48853290 24.60 ns/op 7 B/op 0 allocs/op 156 // BenchmarkHasher_MakeHasher/string-16 50446735 26.41 ns/op 7 B/op 0 allocs/op 157 // BenchmarkHasher_MakeHasher/int-16 314223793 3.722 ns/op 0 B/op 0 allocs/op 158 // BenchmarkHasher_MakeHasher/int-16 327831469 3.681 ns/op 0 B/op 0 allocs/op 159 // BenchmarkHasher_Parallel_MakeHasher-16 759237190 1.611 ns/op 0 B/op 0 allocs/op 160 // BenchmarkHasher_Parallel_MakeHasher-16 800960254 1.598 ns/op 0 B/op 0 allocs/op 161 // BenchmarkHasher_GenHasher64/string-16 43828345 26.33 ns/op 7 B/op 0 allocs/op 162 // BenchmarkHasher_GenHasher64/string-16 43891936 26.14 ns/op 7 B/op 0 allocs/op 163 // BenchmarkHasher_GenHasher64/int-16 470061992 2.594 ns/op 0 B/op 0 allocs/op 164 // BenchmarkHasher_GenHasher64/int-16 459792141 2.596 ns/op 0 B/op 0 allocs/op 165 // BenchmarkHasher_Parallel_GenHasher64-16 333951942 3.606 ns/op 0 B/op 0 allocs/op 166 // BenchmarkHasher_Parallel_GenHasher64-16 321419834 3.627 ns/op 0 B/op 0 allocs/op