blob: 4c15aff967312b82e239a4d47cfe813fc82a8ea7 [file] [log] [blame] [edit]
package z
import (
"hash/fnv"
"math/rand"
"sync/atomic"
"testing"
"time"
"github.com/dgryski/go-farm"
)
func BenchmarkMemHash(b *testing.B) {
buf := make([]byte, 64)
rand.Read(buf)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = MemHash(buf)
}
b.SetBytes(int64(len(buf)))
}
func BenchmarkMemHashString(b *testing.B) {
s := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = MemHashString(s)
}
b.SetBytes(int64(len(s)))
}
func BenchmarkSip(b *testing.B) {
buf := make([]byte, 64)
rand.Read(buf)
for i := 0; i < b.N; i++ {
SipHash(buf)
}
}
func BenchmarkFarm(b *testing.B) {
buf := make([]byte, 64)
rand.Read(buf)
for i := 0; i < b.N; i++ {
farm.Fingerprint64(buf)
}
}
func BenchmarkFnv(b *testing.B) {
buf := make([]byte, 64)
rand.Read(buf)
f := fnv.New64a()
for i := 0; i < b.N; i++ {
f.Write(buf)
f.Sum64()
f.Reset()
}
}
func SipHash(p []byte) (l, h uint64) {
// Initialization.
v0 := uint64(8317987320269560794) // k0 ^ 0x736f6d6570736575
v1 := uint64(7237128889637516672) // k1 ^ 0x646f72616e646f6d
v2 := uint64(7816392314733513934) // k0 ^ 0x6c7967656e657261
v3 := uint64(8387220255325274014) // k1 ^ 0x7465646279746573
t := uint64(len(p)) << 56
// Compression.
for len(p) >= 8 {
m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
v3 ^= m
// Round 1.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// Round 2.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
v0 ^= m
p = p[8:]
}
// Compress last block.
switch len(p) {
case 7:
t |= uint64(p[6]) << 48
fallthrough
case 6:
t |= uint64(p[5]) << 40
fallthrough
case 5:
t |= uint64(p[4]) << 32
fallthrough
case 4:
t |= uint64(p[3]) << 24
fallthrough
case 3:
t |= uint64(p[2]) << 16
fallthrough
case 2:
t |= uint64(p[1]) << 8
fallthrough
case 1:
t |= uint64(p[0])
}
v3 ^= t
// Round 1.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// Round 2.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
v0 ^= t
// Finalization.
v2 ^= 0xff
// Round 1.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// Round 2.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// Round 3.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// Round 4.
v0 += v1
v1 = v1<<13 | v1>>51
v1 ^= v0
v0 = v0<<32 | v0>>32
v2 += v3
v3 = v3<<16 | v3>>48
v3 ^= v2
v0 += v3
v3 = v3<<21 | v3>>43
v3 ^= v0
v2 += v1
v1 = v1<<17 | v1>>47
v1 ^= v2
v2 = v2<<32 | v2>>32
// return v0 ^ v1 ^ v2 ^ v3
hash := v0 ^ v1 ^ v2 ^ v3
h = hash >> 1
l = hash << 1 >> 1
return l, h
}
func BenchmarkNanoTime(b *testing.B) {
for i := 0; i < b.N; i++ {
NanoTime()
}
}
func BenchmarkCPUTicks(b *testing.B) {
for i := 0; i < b.N; i++ {
CPUTicks()
}
}
// goos: linux
// goarch: amd64
// pkg: github.com/dgraph-io/ristretto/z
// BenchmarkFastRand-16 1000000000 0.292 ns/op
// BenchmarkRandSource-16 1000000000 0.747 ns/op
// BenchmarkRandGlobal-16 6822332 176 ns/op
// BenchmarkRandAtomic-16 77950322 15.4 ns/op
// PASS
// ok github.com/dgraph-io/ristretto/z 4.808s
func benchmarkRand(b *testing.B, fab func() func() uint32) {
b.RunParallel(func(pb *testing.PB) {
gen := fab()
for pb.Next() {
gen()
}
})
}
func BenchmarkFastRand(b *testing.B) {
benchmarkRand(b, func() func() uint32 {
return FastRand
})
}
func BenchmarkRandSource(b *testing.B) {
benchmarkRand(b, func() func() uint32 {
s := rand.New(rand.NewSource(time.Now().Unix()))
return func() uint32 { return s.Uint32() }
})
}
func BenchmarkRandGlobal(b *testing.B) {
benchmarkRand(b, func() func() uint32 {
return func() uint32 { return rand.Uint32() }
})
}
func BenchmarkRandAtomic(b *testing.B) {
var x uint32
benchmarkRand(b, func() func() uint32 {
return func() uint32 { return uint32(atomic.AddUint32(&x, 1)) }
})
}