github.com/parquet-go/parquet-go@v0.21.1-0.20240501160520-b3c3a0c3ed6f/hashprobe/aeshash/aeshash_test.go (about) 1 package aeshash 2 3 import ( 4 "encoding/binary" 5 "testing" 6 "time" 7 "unsafe" 8 ) 9 10 //go:noescape 11 //go:linkname runtime_memhash32 runtime.memhash32 12 func runtime_memhash32(data unsafe.Pointer, seed uintptr) uintptr 13 14 //go:noescape 15 //go:linkname runtime_memhash64 runtime.memhash64 16 func runtime_memhash64(data unsafe.Pointer, seed uintptr) uintptr 17 18 //go:noescape 19 //go:linkname runtime_memhash runtime.memhash 20 func runtime_memhash(data unsafe.Pointer, seed, size uintptr) uintptr 21 22 func memhash32(data uint32, seed uintptr) uintptr { 23 return runtime_memhash32(unsafe.Pointer(&data), seed) 24 } 25 26 func memhash64(data uint64, seed uintptr) uintptr { 27 return runtime_memhash64(unsafe.Pointer(&data), seed) 28 } 29 30 func memhash128(data [16]byte, seed uintptr) uintptr { 31 return runtime_memhash(unsafe.Pointer(&data), seed, 16) 32 } 33 34 func TestHash32(t *testing.T) { 35 if !Enabled() { 36 t.Skip("AES hash not supported on this platform") 37 } 38 39 h0 := memhash32(42, 1) 40 h1 := Hash32(42, 1) 41 42 if h0 != h1 { 43 t.Errorf("want=%016x got=%016x", h0, h1) 44 } 45 } 46 47 func TestMultiHash32(t *testing.T) { 48 if !Enabled() { 49 t.Skip("AES hash not supported on this platform") 50 } 51 52 const N = 10 53 hashes := [N]uintptr{} 54 values := [N]uint32{} 55 seed := uintptr(32) 56 57 for i := range values { 58 values[i] = uint32(i) 59 } 60 61 MultiHash32(hashes[:], values[:], seed) 62 63 for i := range values { 64 h := Hash32(values[i], seed) 65 66 if h != hashes[i] { 67 t.Errorf("hash(%d): want=%016x got=%016x", values[i], h, hashes[i]) 68 } 69 } 70 } 71 72 func TestHash64(t *testing.T) { 73 if !Enabled() { 74 t.Skip("AES hash not supported on this platform") 75 } 76 77 h0 := memhash64(42, 1) 78 h1 := Hash64(42, 1) 79 80 if h0 != h1 { 81 t.Errorf("want=%016x got=%016x", h0, h1) 82 } 83 } 84 85 func TestMultiHash64(t *testing.T) { 86 if !Enabled() { 87 t.Skip("AES hash not supported on this platform") 88 } 89 90 const N = 10 91 hashes := [N]uintptr{} 92 values := [N]uint64{} 93 seed := uintptr(64) 94 95 for i := range values { 96 values[i] = uint64(i) 97 } 98 99 MultiHash64(hashes[:], values[:], seed) 100 101 for i := range values { 102 h := Hash64(values[i], seed) 103 104 if h != hashes[i] { 105 t.Errorf("hash(%d): want=%016x got=%016x", values[i], h, hashes[i]) 106 } 107 } 108 } 109 110 func BenchmarkMultiHash64(b *testing.B) { 111 if !Enabled() { 112 b.Skip("AES hash not supported on this platform") 113 } 114 115 hashes := [512]uintptr{} 116 values := [512]uint64{} 117 b.SetBytes(8 * int64(len(hashes))) 118 benchmarkHashThroughput(b, func(seed uintptr) int { 119 MultiHash64(hashes[:], values[:], seed) 120 return len(hashes) 121 }) 122 } 123 124 func TestHash128(t *testing.T) { 125 if !Enabled() { 126 t.Skip("AES hash not supported on this platform") 127 } 128 129 h0 := memhash128([16]byte{0: 42}, 1) 130 h1 := Hash128([16]byte{0: 42}, 1) 131 132 if h0 != h1 { 133 t.Errorf("want=%016x got=%016x", h0, h1) 134 } 135 } 136 137 func TestMultiHash128(t *testing.T) { 138 if !Enabled() { 139 t.Skip("AES hash not supported on this platform") 140 } 141 142 const N = 10 143 hashes := [N]uintptr{} 144 values := [N][16]byte{} 145 seed := uintptr(128) 146 147 for i := range values { 148 binary.LittleEndian.PutUint64(values[i][:8], uint64(i)) 149 } 150 151 MultiHash128(hashes[:], values[:], seed) 152 153 for i := range values { 154 h := Hash128(values[i], seed) 155 156 if h != hashes[i] { 157 t.Errorf("hash(%d): want=%016x got=%016x", values[i], h, hashes[i]) 158 } 159 } 160 } 161 162 func benchmarkHashThroughput(b *testing.B, f func(seed uintptr) int) { 163 hashes := int64(0) 164 start := time.Now() 165 166 for i := 0; i < b.N; i++ { 167 hashes += int64(f(uintptr(i))) 168 } 169 170 seconds := time.Since(start).Seconds() 171 b.ReportMetric(float64(hashes)/seconds, "hash/s") 172 }