github.com/moontrade/nogc@v0.1.7/hash/hash_test.go (about) 1 package hash 2 3 import ( 4 "encoding/binary" 5 "hash/crc32" 6 "hash/crc64" 7 "math/rand" 8 "testing" 9 ) 10 11 func TestHashCollisions_WASM(t *testing.T) { 12 var ( 13 c32 int 14 a32 int 15 c16 int 16 fn int 17 mur int 18 wy int 19 wy64 int 20 met int 21 met64 int 22 total int 23 ) 24 25 type config struct { 26 low int 27 high int 28 adder int 29 factor float64 30 addressStart int 31 multiplierLow int 32 multiplierHigh int 33 multiplierAdd int 34 } 35 for _, cfg := range []config{ 36 //{2, 10, 4, 8, 65580, 64, 4096, 128}, 37 // WASM like pointer values 38 {40, 1024, 88, 3, 65580, 512, 256000, 96}, 39 {1024, 4096, 512, 3, 65580, 56, 52050, 512}, 40 } { 41 for i := cfg.low; i < cfg.high; i += cfg.adder { 42 var ( 43 entries = i 44 slots = int(float64(i) * cfg.factor) 45 ) 46 for multiplier := cfg.multiplierLow; multiplier < cfg.multiplierHigh; multiplier += cfg.multiplierAdd { 47 total += entries 48 c32 += testCollisions(entries, multiplier, slots, crc32h) 49 c16 += testCollisions(entries, multiplier, slots, crc16a) 50 a32 += testCollisions(entries, multiplier, slots, Adler32) 51 fn += testCollisions(entries, multiplier, slots, FNV32) 52 mur += testCollisions(entries, multiplier, slots, Murmur32) 53 wy += testCollisions(entries, multiplier, slots, WyHash32) 54 wy64 += testCollisions64(entries, multiplier, slots, WyHash64) 55 met += testCollisions(entries, multiplier, slots, Metro32) 56 met64 += testCollisions64(entries, multiplier, slots, Metro64) 57 } 58 } 59 60 //println("\tcrc32 ", c32) 61 //println("\tcrc16 ", c16) 62 //println("\tadler32 ", a32) 63 //println("\tfnv ", fn) 64 //println("\tmurmur32 ", mur) 65 //println("\twyhash32 ", wy) 66 //println("\twyhash64 ", wy64) 67 //println("\tmetro32 ", met) 68 //println("\tmetro64 ", met64) 69 } 70 71 println("") 72 println("total ", total) 73 println("\tcrc32 ", c32) 74 println("\tcrc16 ", c16) 75 println("\tAdler32 ", a32) 76 println("\tfnv ", fn) 77 println("\tMurmur32 ", mur) 78 println("\tWyHash32 ", wy) 79 println("\tWyHash64 ", wy64) 80 println("\tMetro32 ", met) 81 println("\tMetro64 ", met64) 82 } 83 84 func rangeRandom(min, max uint32) uint32 { 85 return uint32(rand.Int31n(int32(max-min)) + int32(min)) 86 } 87 88 func testCollisions(entries, multiplier, slots int, hasher func(uint32) uint32) int { 89 m := make(map[uint32]struct{}) 90 count := 0 91 92 ptr := 65680 93 94 for i := 0; i < entries; i++ { 95 v := hasher(uint32(ptr)) 96 ptr += multiplier 97 index := v % uint32(slots) 98 99 _, ok := m[index] 100 if ok { 101 count++ 102 } else { 103 m[index] = struct{}{} 104 } 105 } 106 return count 107 } 108 109 func testCollisionsRandom(entries, slots int, hasher func(uint32) uint32) int { 110 m := make(map[uint32]struct{}) 111 count := 0 112 113 for i := 0; i < entries; i++ { 114 v := hasher(uint32(rand.Uint32())) 115 index := v % uint32(slots) 116 117 _, ok := m[index] 118 if ok { 119 count++ 120 } else { 121 m[index] = struct{}{} 122 } 123 } 124 return count 125 } 126 127 func testCollisions64(entries, multiplier, slots int, hasher func(uint64) uint64) int { 128 m := make(map[uint64]struct{}) 129 count := 0 130 131 ptr := 65536 132 133 for i := uint64(0); i < uint64(entries); i++ { 134 v := hasher(uint64(ptr)) 135 ptr += multiplier 136 index := v % uint64(slots) 137 138 _, ok := m[index] 139 if ok { 140 count++ 141 } else { 142 m[index] = struct{}{} 143 } 144 } 145 return count 146 } 147 148 func crc64h(v uint32) uint32 { 149 h := crc64.New(crc64.MakeTable(crc64.ECMA)) 150 h.Reset() 151 b := [4]byte{} 152 binary.LittleEndian.PutUint32(b[0:], v) 153 h.Write(b[0:4]) 154 return uint32(h.Sum64()) 155 } 156 157 func crc32h(v uint32) uint32 { 158 h := crc32.NewIEEE() 159 h.Reset() 160 b := [4]byte{} 161 binary.LittleEndian.PutUint32(b[0:], v) 162 h.Write(b[0:4]) 163 return uint32(h.Sum32()) 164 } 165 166 var crc16tab = [256]uint16{ 167 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 168 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 169 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 170 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 171 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 172 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 173 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 174 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 175 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 176 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 177 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 178 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 179 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 180 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 181 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 182 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 183 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 184 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 185 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 186 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 187 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 188 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 189 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 190 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 191 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 192 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 193 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 194 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 195 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 196 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 197 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 198 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0} 199 200 func crc16a(v uint32) uint32 { 201 crc := uint16(0) 202 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v))] 203 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<8))] 204 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<16))] 205 crc = ((crc << 8) & 0xff00) ^ crc16tab[((crc>>8)&0xff)^uint16(byte(v<<24))] 206 return uint32(crc) 207 } 208 209 func BenchmarkHash(b *testing.B) { 210 //b.Run("crc32", func(b *testing.B) { 211 // for i := 0; i < b.N; i++ { 212 // crc32h(23) 213 // } 214 //}) 215 //b.Run("crc16", func(b *testing.B) { 216 // for i := 0; i < b.N; i++ { 217 // crc16a(23) 218 // } 219 //}) 220 //b.Run("crc16", func(b *testing.B) { 221 // for i := 0; i < b.N; i++ { 222 // crc16a(23) 223 // } 224 //}) 225 b.Run("Adler32", func(b *testing.B) { 226 for i := 0; i < b.N; i++ { 227 Adler32(Adler32(uint32(i))) 228 } 229 }) 230 b.Run("FNV32", func(b *testing.B) { 231 for i := 0; i < b.N; i++ { 232 FNV32(FNV32(uint32(i))) 233 } 234 }) 235 b.Run("Murmur32", func(b *testing.B) { 236 for i := 0; i < b.N; i++ { 237 Murmur32(Murmur32(uint32(i))) 238 } 239 }) 240 b.Run("WyHash32", func(b *testing.B) { 241 for i := 0; i < b.N; i++ { 242 WyHash32(WyHash32(uint32(i))) 243 } 244 }) 245 b.Run("WyHash64", func(b *testing.B) { 246 for i := 0; i < b.N; i++ { 247 WyHash64(WyHash64(uint64(i))) 248 } 249 }) 250 b.Run("Metro32", func(b *testing.B) { 251 for i := 0; i < b.N; i++ { 252 Metro32(Metro32(uint32(i))) 253 } 254 }) 255 b.Run("Metro64", func(b *testing.B) { 256 for i := 0; i < b.N; i++ { 257 Metro64(Metro64(uint64(i))) 258 } 259 }) 260 //b.Run("WyHash", func(b *testing.B) { 261 // h := fnv.New32a() 262 // for i := 0; i < b.N; i++ { 263 // h.Reset() 264 // 265 // WyHash32(23) 266 // } 267 //}) 268 }