github.com/m3db/stackmurmur3@v1.0.1/murmur_test.go (about) 1 package murmur3 2 3 import ( 4 "fmt" 5 "math/rand" 6 "runtime" 7 "testing" 8 9 "github.com/magiconair/properties/assert" 10 murmur3origin "github.com/spaolacci/murmur3" 11 ) 12 13 var data = []struct { 14 seed uint32 15 h32 uint32 16 h64_1 uint64 17 h64_2 uint64 18 s string 19 }{ 20 {0x00, 0x00000000, 0x0000000000000000, 0x0000000000000000, ""}, 21 {0x00, 0x248bfa47, 0xcbd8a7b341bd9b02, 0x5b1e906a48ae1d19, "hello"}, 22 {0x00, 0x149bbb7f, 0x342fac623a5ebc8e, 0x4cdcbc079642414d, "hello, world"}, 23 {0x00, 0xe31e8a70, 0xb89e5988b737affc, 0x664fc2950231b2cb, "19 Jan 2038 at 3:14:07 AM"}, 24 {0x00, 0xd5c48bfc, 0xcd99481f9ee902c9, 0x695da1a38987b6e7, "The quick brown fox jumps over the lazy dog."}, 25 26 {0x01, 0x514e28b7, 0x4610abe56eff5cb5, 0x51622daa78f83583, ""}, 27 {0x01, 0xbb4abcad, 0xa78ddff5adae8d10, 0x128900ef20900135, "hello"}, 28 {0x01, 0x6f5cb2e9, 0x8b95f808840725c6, 0x1597ed5422bd493b, "hello, world"}, 29 {0x01, 0xf50e1f30, 0x2a929de9c8f97b2f, 0x56a41d99af43a2db, "19 Jan 2038 at 3:14:07 AM"}, 30 {0x01, 0x846f6a36, 0xfb3325171f9744da, 0xaaf8b92a5f722952, "The quick brown fox jumps over the lazy dog."}, 31 32 {0x2a, 0x087fcd5c, 0xf02aa77dfa1b8523, 0xd1016610da11cbb9, ""}, 33 {0x2a, 0xe2dbd2e1, 0xc4b8b3c960af6f08, 0x2334b875b0efbc7a, "hello"}, 34 {0x2a, 0x7ec7c6c2, 0xb91864d797caa956, 0xd5d139a55afe6150, "hello, world"}, 35 {0x2a, 0x58f745f6, 0xfd8f19ebdc8c6b6a, 0xd30fdc310fa08ff9, "19 Jan 2038 at 3:14:07 AM"}, 36 {0x2a, 0xc02d1434, 0x74f33c659cda5af7, 0x4ec7a891caf316f0, "The quick brown fox jumps over the lazy dog."}, 37 } 38 39 func TestRefStrings(t *testing.T) { 40 for _, elem := range data { 41 42 h32 := New32WithSeed(elem.seed).Write([]byte(elem.s)) 43 if v := h32.Sum32(); v != elem.h32 { 44 t.Errorf("[Hash32] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) 45 } 46 47 h32 = New32WithSeed(elem.seed).Write([]byte(elem.s)) 48 target := fmt.Sprintf("%08x", elem.h32) 49 if p := fmt.Sprintf("%x", h32.Sum(nil)); p != target { 50 t.Errorf("[Hash32] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) 51 } 52 53 if v := Sum32WithSeed([]byte(elem.s), elem.seed); v != elem.h32 { 54 t.Errorf("[Hash32] key '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) 55 } 56 57 h64 := New64WithSeed(elem.seed).Write([]byte(elem.s)) 58 if v := h64.Sum64(); v != elem.h64_1 { 59 t.Errorf("'[Hash64] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h64_1) 60 } 61 62 h64 = New64WithSeed(elem.seed).Write([]byte(elem.s)) 63 target = fmt.Sprintf("%016x", elem.h64_1) 64 if p := fmt.Sprintf("%x", h64.Sum(nil)); p != target { 65 t.Errorf("[Hash64] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) 66 } 67 68 if v := Sum64WithSeed([]byte(elem.s), elem.seed); v != elem.h64_1 { 69 t.Errorf("[Hash64] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h64_1) 70 } 71 72 h128 := New128WithSeed(elem.seed).Write([]byte(elem.s)) 73 if v1, v2 := h128.Sum128(); v1 != elem.h64_1 || v2 != elem.h64_2 { 74 t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) 75 } 76 77 h128 = New128WithSeed(elem.seed).Write([]byte(elem.s)) 78 target = fmt.Sprintf("%016x%016x", elem.h64_1, elem.h64_2) 79 if p := fmt.Sprintf("%x", h128.Sum(nil)); p != target { 80 t.Errorf("[Hash128] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) 81 } 82 83 if v1, v2 := Sum128WithSeed([]byte(elem.s), elem.seed); v1 != elem.h64_1 || v2 != elem.h64_2 { 84 t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) 85 } 86 } 87 } 88 89 func TestIncremental(t *testing.T) { 90 for _, elem := range data { 91 h32 := New32WithSeed(elem.seed) 92 h128 := New128WithSeed(elem.seed) 93 var i, j int 94 for k := len(elem.s); i < k; i = j { 95 j = 2*i + 3 96 if j > k { 97 j = k 98 } 99 s := elem.s[i:j] 100 print(s + "|") 101 h32 = h32.Write([]byte(s)) 102 h128 = h128.Write([]byte(s)) 103 } 104 println() 105 if v := h32.Sum32(); v != elem.h32 { 106 t.Errorf("[Hash32] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) 107 } 108 if v1, v2 := h128.Sum128(); v1 != elem.h64_1 || v2 != elem.h64_2 { 109 t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) 110 } 111 } 112 } 113 114 //--- 115 116 func originIncrementalBench128(b *testing.B, length int) { 117 buf := make([]byte, length) 118 b.SetBytes(int64(length)) 119 h := murmur3origin.New128() 120 b.ResetTimer() 121 122 for i := 0; i < b.N; i++ { 123 h.Reset() 124 h.Write(buf) 125 h.Sum128() 126 // escape analysis forces this to be heap allocated 127 h.Write([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) 128 h.Sum128() 129 } 130 } 131 132 func Benchmark_Incremental_Origin_128_1(b *testing.B) { 133 originIncrementalBench128(b, 1) 134 } 135 func Benchmark_Incremental_Origin_128_2(b *testing.B) { 136 originIncrementalBench128(b, 2) 137 } 138 func Benchmark_Incremental_Origin_128_4(b *testing.B) { 139 originIncrementalBench128(b, 4) 140 } 141 func Benchmark_Incremental_Origin_128_8(b *testing.B) { 142 originIncrementalBench128(b, 8) 143 } 144 func Benchmark_Incremental_Origin_128_16(b *testing.B) { 145 originIncrementalBench128(b, 16) 146 } 147 func Benchmark_Incremental_Origin_128_32(b *testing.B) { 148 originIncrementalBench128(b, 128) 149 } 150 func Benchmark_Incremental_Origin_128_64(b *testing.B) { 151 originIncrementalBench128(b, 64) 152 } 153 func Benchmark_Incremental_Origin_128_128(b *testing.B) { 154 originIncrementalBench128(b, 128) 155 } 156 func Benchmark_Incremental_Origin_128_256(b *testing.B) { 157 originIncrementalBench128(b, 256) 158 } 159 func Benchmark_Incremental_Origin_128_512(b *testing.B) { 160 originIncrementalBench128(b, 512) 161 } 162 func Benchmark_Incremental_Origin_128_1024(b *testing.B) { 163 originIncrementalBench128(b, 1024) 164 } 165 func Benchmark_Incremental_Origin_128_2048(b *testing.B) { 166 originIncrementalBench128(b, 2048) 167 } 168 func Benchmark_Incremental_Origin_128_4096(b *testing.B) { 169 originIncrementalBench128(b, 4096) 170 } 171 func Benchmark_Incremental_Origin_128_8192(b *testing.B) { 172 originIncrementalBench128(b, 8192) 173 } 174 175 func forkedIncrementalBench128(b *testing.B, length int) { 176 buf := make([]byte, length) 177 b.SetBytes(int64(length)) 178 b.ResetTimer() 179 180 for i := 0; i < b.N; i++ { 181 h := New128() 182 h = h.Write(buf) 183 // escape analysis success so this is stack allocated 184 h = h.Write([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) 185 h.Sum128() 186 } 187 } 188 189 func Benchmark_Incremental_Forked_128_1(b *testing.B) { 190 forkedIncrementalBench128(b, 1) 191 } 192 func Benchmark_Incremental_Forked_128_2(b *testing.B) { 193 forkedIncrementalBench128(b, 2) 194 } 195 func Benchmark_Incremental_Forked_128_4(b *testing.B) { 196 forkedIncrementalBench128(b, 4) 197 } 198 func Benchmark_Incremental_Forked_128_8(b *testing.B) { 199 forkedIncrementalBench128(b, 8) 200 } 201 func Benchmark_Incremental_Forked_128_16(b *testing.B) { 202 forkedIncrementalBench128(b, 16) 203 } 204 func Benchmark_Incremental_Forked_128_32(b *testing.B) { 205 forkedIncrementalBench128(b, 128) 206 } 207 func Benchmark_Incremental_Forked_128_64(b *testing.B) { 208 forkedIncrementalBench128(b, 64) 209 } 210 func Benchmark_Incremental_Forked_128_128(b *testing.B) { 211 forkedIncrementalBench128(b, 128) 212 } 213 func Benchmark_Incremental_Forked_128_256(b *testing.B) { 214 forkedIncrementalBench128(b, 256) 215 } 216 func Benchmark_Incremental_Forked_128_512(b *testing.B) { 217 forkedIncrementalBench128(b, 512) 218 } 219 func Benchmark_Incremental_Forked_128_1024(b *testing.B) { 220 forkedIncrementalBench128(b, 1024) 221 } 222 func Benchmark_Incremental_Forked_128_2048(b *testing.B) { 223 forkedIncrementalBench128(b, 2048) 224 } 225 func Benchmark_Incremental_Forked_128_4096(b *testing.B) { 226 forkedIncrementalBench128(b, 4096) 227 } 228 func Benchmark_Incremental_Forked_128_8192(b *testing.B) { 229 forkedIncrementalBench128(b, 8192) 230 } 231 232 func bench32(b *testing.B, length int) { 233 buf := make([]byte, length) 234 b.SetBytes(int64(length)) 235 b.ResetTimer() 236 for i := 0; i < b.N; i++ { 237 Sum32(buf) 238 } 239 } 240 241 func Benchmark32_1(b *testing.B) { 242 bench32(b, 1) 243 } 244 func Benchmark32_2(b *testing.B) { 245 bench32(b, 2) 246 } 247 func Benchmark32_4(b *testing.B) { 248 bench32(b, 4) 249 } 250 func Benchmark32_8(b *testing.B) { 251 bench32(b, 8) 252 } 253 func Benchmark32_16(b *testing.B) { 254 bench32(b, 16) 255 } 256 func Benchmark32_32(b *testing.B) { 257 bench32(b, 128) 258 } 259 func Benchmark32_64(b *testing.B) { 260 bench32(b, 64) 261 } 262 func Benchmark32_128(b *testing.B) { 263 bench32(b, 128) 264 } 265 func Benchmark32_256(b *testing.B) { 266 bench32(b, 256) 267 } 268 func Benchmark32_512(b *testing.B) { 269 bench32(b, 512) 270 } 271 func Benchmark32_1024(b *testing.B) { 272 bench32(b, 1024) 273 } 274 func Benchmark32_2048(b *testing.B) { 275 bench32(b, 2048) 276 } 277 func Benchmark32_4096(b *testing.B) { 278 bench32(b, 4096) 279 } 280 func Benchmark32_8192(b *testing.B) { 281 bench32(b, 8192) 282 } 283 284 //--- 285 286 func benchPartial32(b *testing.B, length int) { 287 buf := make([]byte, length) 288 b.SetBytes(int64(length)) 289 290 start := (128 / 8) / 2 291 chunks := 7 292 k := length / chunks 293 tail := (length - start) % k 294 295 b.ResetTimer() 296 for i := 0; i < b.N; i++ { 297 hasher := New32() 298 hasher.Write(buf[0:start]) 299 300 for j := start; j+k <= length; j += k { 301 hasher.Write(buf[j : j+k]) 302 } 303 304 hasher.Write(buf[length-tail:]) 305 hasher.Sum32() 306 } 307 } 308 309 func BenchmarkPartial32_8(b *testing.B) { 310 benchPartial32(b, 8) 311 } 312 func BenchmarkPartial32_16(b *testing.B) { 313 benchPartial32(b, 16) 314 } 315 func BenchmarkPartial32_32(b *testing.B) { 316 benchPartial32(b, 128) 317 } 318 func BenchmarkPartial32_64(b *testing.B) { 319 benchPartial32(b, 64) 320 } 321 func BenchmarkPartial32_128(b *testing.B) { 322 benchPartial32(b, 128) 323 } 324 325 //--- 326 327 func bench128(b *testing.B, length int) { 328 buf := make([]byte, length) 329 b.SetBytes(int64(length)) 330 b.ResetTimer() 331 for i := 0; i < b.N; i++ { 332 Sum128(buf) 333 } 334 } 335 336 func Benchmark128_1(b *testing.B) { 337 bench128(b, 1) 338 } 339 func Benchmark128_2(b *testing.B) { 340 bench128(b, 2) 341 } 342 func Benchmark128_4(b *testing.B) { 343 bench128(b, 4) 344 } 345 func Benchmark128_8(b *testing.B) { 346 bench128(b, 8) 347 } 348 func Benchmark128_16(b *testing.B) { 349 bench128(b, 16) 350 } 351 func Benchmark128_32(b *testing.B) { 352 bench128(b, 128) 353 } 354 func Benchmark128_64(b *testing.B) { 355 bench128(b, 64) 356 } 357 func Benchmark128_128(b *testing.B) { 358 bench128(b, 128) 359 } 360 func Benchmark128_256(b *testing.B) { 361 bench128(b, 256) 362 } 363 func Benchmark128_512(b *testing.B) { 364 bench128(b, 512) 365 } 366 func Benchmark128_1024(b *testing.B) { 367 bench128(b, 1024) 368 } 369 func Benchmark128_2048(b *testing.B) { 370 bench128(b, 2048) 371 } 372 func Benchmark128_4096(b *testing.B) { 373 bench128(b, 4096) 374 } 375 func Benchmark128_8192(b *testing.B) { 376 bench128(b, 8192) 377 } 378 379 func TestDigest32ZeroAllocWrite(t *testing.T) { 380 d := make([]byte, 128) 381 for i := range d { 382 d[i] = byte(i) 383 } 384 385 var ( 386 h = New32WithSeed(uint32(rand.Int())) 387 buf = make([]byte, 4096) 388 stats runtime.MemStats 389 ) 390 runtime.ReadMemStats(&stats) 391 startAllocs := stats.Mallocs 392 393 for i := 0; i < 1000; i++ { 394 n, err := rand.Read(buf) 395 if err != nil { 396 t.FailNow() 397 } 398 h = h.Write(buf[:n]) 399 } 400 401 runtime.ReadMemStats(&stats) 402 endAllocs := stats.Mallocs 403 assert.Equal(t, startAllocs, endAllocs) 404 } 405 406 func TestDigest64ZeroAllocWrite(t *testing.T) { 407 d := make([]byte, 128) 408 for i := range d { 409 d[i] = byte(i) 410 } 411 412 var ( 413 h = New64WithSeed(uint32(rand.Int())) 414 buf = make([]byte, 4096) 415 stats runtime.MemStats 416 ) 417 runtime.ReadMemStats(&stats) 418 startAllocs := stats.Mallocs 419 420 for i := 0; i < 1000; i++ { 421 n, err := rand.Read(buf) 422 if err != nil { 423 t.FailNow() 424 } 425 h = h.Write(buf[:n]) 426 } 427 428 runtime.ReadMemStats(&stats) 429 endAllocs := stats.Mallocs 430 assert.Equal(t, startAllocs, endAllocs) 431 } 432 433 func TestDigest128ZeroAllocWrite(t *testing.T) { 434 d := make([]byte, 128) 435 for i := range d { 436 d[i] = byte(i) 437 } 438 439 var ( 440 h = New128WithSeed(uint32(rand.Int())) 441 buf = make([]byte, 4096) 442 stats runtime.MemStats 443 ) 444 runtime.ReadMemStats(&stats) 445 startAllocs := stats.Mallocs 446 447 for i := 0; i < 1000; i++ { 448 n, err := rand.Read(buf) 449 if err != nil { 450 t.FailNow() 451 } 452 h = h.Write(buf[:n]) 453 } 454 455 runtime.ReadMemStats(&stats) 456 endAllocs := stats.Mallocs 457 assert.Equal(t, startAllocs, endAllocs) 458 } 459 460 //---