github.com/dgraph-io/ristretto@v0.1.2-0.20240116140435-c67e07994f91/z/rtutil_test.go (about)

     1  package z
     2  
     3  import (
     4  	"hash/fnv"
     5  	"math/rand"
     6  	"sync/atomic"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/dgryski/go-farm"
    11  )
    12  
    13  func BenchmarkMemHash(b *testing.B) {
    14  	buf := make([]byte, 64)
    15  	rand.Read(buf)
    16  
    17  	b.ReportAllocs()
    18  	b.ResetTimer()
    19  	for i := 0; i < b.N; i++ {
    20  		_ = MemHash(buf)
    21  	}
    22  	b.SetBytes(int64(len(buf)))
    23  }
    24  
    25  func BenchmarkMemHashString(b *testing.B) {
    26  	s := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " +
    27  		"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    28  
    29  	b.ReportAllocs()
    30  	b.ResetTimer()
    31  	for i := 0; i < b.N; i++ {
    32  		_ = MemHashString(s)
    33  	}
    34  	b.SetBytes(int64(len(s)))
    35  }
    36  
    37  func BenchmarkSip(b *testing.B) {
    38  	buf := make([]byte, 64)
    39  	rand.Read(buf)
    40  	for i := 0; i < b.N; i++ {
    41  		SipHash(buf)
    42  	}
    43  }
    44  
    45  func BenchmarkFarm(b *testing.B) {
    46  	buf := make([]byte, 64)
    47  	rand.Read(buf)
    48  	for i := 0; i < b.N; i++ {
    49  		farm.Fingerprint64(buf)
    50  	}
    51  }
    52  
    53  func BenchmarkFnv(b *testing.B) {
    54  	buf := make([]byte, 64)
    55  	rand.Read(buf)
    56  	f := fnv.New64a()
    57  	for i := 0; i < b.N; i++ {
    58  		f.Write(buf)
    59  		f.Sum64()
    60  		f.Reset()
    61  	}
    62  }
    63  
    64  func SipHash(p []byte) (l, h uint64) {
    65  	// Initialization.
    66  	v0 := uint64(8317987320269560794) // k0 ^ 0x736f6d6570736575
    67  	v1 := uint64(7237128889637516672) // k1 ^ 0x646f72616e646f6d
    68  	v2 := uint64(7816392314733513934) // k0 ^ 0x6c7967656e657261
    69  	v3 := uint64(8387220255325274014) // k1 ^ 0x7465646279746573
    70  	t := uint64(len(p)) << 56
    71  
    72  	// Compression.
    73  	for len(p) >= 8 {
    74  		m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
    75  			uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
    76  
    77  		v3 ^= m
    78  
    79  		// Round 1.
    80  		v0 += v1
    81  		v1 = v1<<13 | v1>>51
    82  		v1 ^= v0
    83  		v0 = v0<<32 | v0>>32
    84  
    85  		v2 += v3
    86  		v3 = v3<<16 | v3>>48
    87  		v3 ^= v2
    88  
    89  		v0 += v3
    90  		v3 = v3<<21 | v3>>43
    91  		v3 ^= v0
    92  
    93  		v2 += v1
    94  		v1 = v1<<17 | v1>>47
    95  		v1 ^= v2
    96  		v2 = v2<<32 | v2>>32
    97  
    98  		// Round 2.
    99  		v0 += v1
   100  		v1 = v1<<13 | v1>>51
   101  		v1 ^= v0
   102  		v0 = v0<<32 | v0>>32
   103  
   104  		v2 += v3
   105  		v3 = v3<<16 | v3>>48
   106  		v3 ^= v2
   107  
   108  		v0 += v3
   109  		v3 = v3<<21 | v3>>43
   110  		v3 ^= v0
   111  
   112  		v2 += v1
   113  		v1 = v1<<17 | v1>>47
   114  		v1 ^= v2
   115  		v2 = v2<<32 | v2>>32
   116  
   117  		v0 ^= m
   118  		p = p[8:]
   119  	}
   120  
   121  	// Compress last block.
   122  	switch len(p) {
   123  	case 7:
   124  		t |= uint64(p[6]) << 48
   125  		fallthrough
   126  	case 6:
   127  		t |= uint64(p[5]) << 40
   128  		fallthrough
   129  	case 5:
   130  		t |= uint64(p[4]) << 32
   131  		fallthrough
   132  	case 4:
   133  		t |= uint64(p[3]) << 24
   134  		fallthrough
   135  	case 3:
   136  		t |= uint64(p[2]) << 16
   137  		fallthrough
   138  	case 2:
   139  		t |= uint64(p[1]) << 8
   140  		fallthrough
   141  	case 1:
   142  		t |= uint64(p[0])
   143  	}
   144  
   145  	v3 ^= t
   146  
   147  	// Round 1.
   148  	v0 += v1
   149  	v1 = v1<<13 | v1>>51
   150  	v1 ^= v0
   151  	v0 = v0<<32 | v0>>32
   152  
   153  	v2 += v3
   154  	v3 = v3<<16 | v3>>48
   155  	v3 ^= v2
   156  
   157  	v0 += v3
   158  	v3 = v3<<21 | v3>>43
   159  	v3 ^= v0
   160  
   161  	v2 += v1
   162  	v1 = v1<<17 | v1>>47
   163  	v1 ^= v2
   164  	v2 = v2<<32 | v2>>32
   165  
   166  	// Round 2.
   167  	v0 += v1
   168  	v1 = v1<<13 | v1>>51
   169  	v1 ^= v0
   170  	v0 = v0<<32 | v0>>32
   171  
   172  	v2 += v3
   173  	v3 = v3<<16 | v3>>48
   174  	v3 ^= v2
   175  
   176  	v0 += v3
   177  	v3 = v3<<21 | v3>>43
   178  	v3 ^= v0
   179  
   180  	v2 += v1
   181  	v1 = v1<<17 | v1>>47
   182  	v1 ^= v2
   183  	v2 = v2<<32 | v2>>32
   184  
   185  	v0 ^= t
   186  
   187  	// Finalization.
   188  	v2 ^= 0xff
   189  
   190  	// Round 1.
   191  	v0 += v1
   192  	v1 = v1<<13 | v1>>51
   193  	v1 ^= v0
   194  	v0 = v0<<32 | v0>>32
   195  
   196  	v2 += v3
   197  	v3 = v3<<16 | v3>>48
   198  	v3 ^= v2
   199  
   200  	v0 += v3
   201  	v3 = v3<<21 | v3>>43
   202  	v3 ^= v0
   203  
   204  	v2 += v1
   205  	v1 = v1<<17 | v1>>47
   206  	v1 ^= v2
   207  	v2 = v2<<32 | v2>>32
   208  
   209  	// Round 2.
   210  	v0 += v1
   211  	v1 = v1<<13 | v1>>51
   212  	v1 ^= v0
   213  	v0 = v0<<32 | v0>>32
   214  
   215  	v2 += v3
   216  	v3 = v3<<16 | v3>>48
   217  	v3 ^= v2
   218  
   219  	v0 += v3
   220  	v3 = v3<<21 | v3>>43
   221  	v3 ^= v0
   222  
   223  	v2 += v1
   224  	v1 = v1<<17 | v1>>47
   225  	v1 ^= v2
   226  	v2 = v2<<32 | v2>>32
   227  
   228  	// Round 3.
   229  	v0 += v1
   230  	v1 = v1<<13 | v1>>51
   231  	v1 ^= v0
   232  	v0 = v0<<32 | v0>>32
   233  
   234  	v2 += v3
   235  	v3 = v3<<16 | v3>>48
   236  	v3 ^= v2
   237  
   238  	v0 += v3
   239  	v3 = v3<<21 | v3>>43
   240  	v3 ^= v0
   241  
   242  	v2 += v1
   243  	v1 = v1<<17 | v1>>47
   244  	v1 ^= v2
   245  	v2 = v2<<32 | v2>>32
   246  
   247  	// Round 4.
   248  	v0 += v1
   249  	v1 = v1<<13 | v1>>51
   250  	v1 ^= v0
   251  	v0 = v0<<32 | v0>>32
   252  
   253  	v2 += v3
   254  	v3 = v3<<16 | v3>>48
   255  	v3 ^= v2
   256  
   257  	v0 += v3
   258  	v3 = v3<<21 | v3>>43
   259  	v3 ^= v0
   260  
   261  	v2 += v1
   262  	v1 = v1<<17 | v1>>47
   263  	v1 ^= v2
   264  	v2 = v2<<32 | v2>>32
   265  
   266  	// return v0 ^ v1 ^ v2 ^ v3
   267  
   268  	hash := v0 ^ v1 ^ v2 ^ v3
   269  	h = hash >> 1
   270  	l = hash << 1 >> 1
   271  	return l, h
   272  }
   273  
   274  func BenchmarkNanoTime(b *testing.B) {
   275  	for i := 0; i < b.N; i++ {
   276  		NanoTime()
   277  	}
   278  }
   279  
   280  func BenchmarkCPUTicks(b *testing.B) {
   281  	for i := 0; i < b.N; i++ {
   282  		CPUTicks()
   283  	}
   284  }
   285  
   286  // goos: linux
   287  // goarch: amd64
   288  // pkg: github.com/dgraph-io/ristretto/z
   289  // BenchmarkFastRand-16      	1000000000	         0.292 ns/op
   290  // BenchmarkRandSource-16    	1000000000	         0.747 ns/op
   291  // BenchmarkRandGlobal-16    	 6822332	       176 ns/op
   292  // BenchmarkRandAtomic-16    	77950322	        15.4 ns/op
   293  // PASS
   294  // ok  	github.com/dgraph-io/ristretto/z	4.808s
   295  func benchmarkRand(b *testing.B, fab func() func() uint32) {
   296  	b.RunParallel(func(pb *testing.PB) {
   297  		gen := fab()
   298  		for pb.Next() {
   299  			gen()
   300  		}
   301  	})
   302  }
   303  
   304  func BenchmarkFastRand(b *testing.B) {
   305  	benchmarkRand(b, func() func() uint32 {
   306  		return FastRand
   307  	})
   308  }
   309  
   310  func BenchmarkRandSource(b *testing.B) {
   311  	benchmarkRand(b, func() func() uint32 {
   312  		s := rand.New(rand.NewSource(time.Now().Unix()))
   313  		return func() uint32 { return s.Uint32() }
   314  	})
   315  }
   316  
   317  func BenchmarkRandGlobal(b *testing.B) {
   318  	benchmarkRand(b, func() func() uint32 {
   319  		return func() uint32 { return rand.Uint32() }
   320  	})
   321  }
   322  
   323  func BenchmarkRandAtomic(b *testing.B) {
   324  	var x uint32
   325  	benchmarkRand(b, func() func() uint32 {
   326  		return func() uint32 { return atomic.AddUint32(&x, 1) }
   327  	})
   328  }