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  //---