mirror of https://github.com/tidwall/tile38.git
161 lines
3.5 KiB
Go
161 lines
3.5 KiB
Go
package xxhashbench
|
|
|
|
import (
|
|
"fmt"
|
|
"hash/crc32"
|
|
"hash/fnv"
|
|
"testing"
|
|
|
|
OneOfOne "github.com/OneOfOne/xxhash"
|
|
"github.com/cespare/xxhash/v2"
|
|
"github.com/spaolacci/murmur3"
|
|
)
|
|
|
|
var sink uint64
|
|
|
|
var benchmarks = []struct {
|
|
name string
|
|
directBytes func([]byte) uint64
|
|
directString func(string) uint64
|
|
digestBytes func([]byte) uint64
|
|
digestString func(string) uint64
|
|
}{
|
|
{
|
|
name: "xxhash",
|
|
directBytes: xxhash.Sum64,
|
|
directString: xxhash.Sum64String,
|
|
digestBytes: func(b []byte) uint64 {
|
|
h := xxhash.New()
|
|
h.Write(b)
|
|
return h.Sum64()
|
|
},
|
|
digestString: func(s string) uint64 {
|
|
h := xxhash.New()
|
|
h.WriteString(s)
|
|
return h.Sum64()
|
|
},
|
|
},
|
|
{
|
|
name: "OneOfOne",
|
|
directBytes: OneOfOne.Checksum64,
|
|
directString: OneOfOne.ChecksumString64,
|
|
digestBytes: func(b []byte) uint64 {
|
|
h := OneOfOne.New64()
|
|
h.Write(b)
|
|
return h.Sum64()
|
|
},
|
|
digestString: func(s string) uint64 {
|
|
h := OneOfOne.New64()
|
|
h.WriteString(s)
|
|
return h.Sum64()
|
|
},
|
|
},
|
|
{
|
|
name: "murmur3",
|
|
directBytes: murmur3.Sum64,
|
|
directString: func(s string) uint64 {
|
|
return murmur3.Sum64([]byte(s))
|
|
},
|
|
digestBytes: func(b []byte) uint64 {
|
|
h := murmur3.New64()
|
|
h.Write(b)
|
|
return h.Sum64()
|
|
},
|
|
digestString: func(s string) uint64 {
|
|
h := murmur3.New64()
|
|
h.Write([]byte(s))
|
|
return h.Sum64()
|
|
},
|
|
},
|
|
{
|
|
name: "CRC-32",
|
|
directBytes: func(b []byte) uint64 {
|
|
return uint64(crc32.ChecksumIEEE(b))
|
|
},
|
|
directString: func(s string) uint64 {
|
|
return uint64(crc32.ChecksumIEEE([]byte(s)))
|
|
},
|
|
digestBytes: func(b []byte) uint64 {
|
|
h := crc32.NewIEEE()
|
|
h.Write(b)
|
|
return uint64(h.Sum32())
|
|
},
|
|
digestString: func(s string) uint64 {
|
|
h := crc32.NewIEEE()
|
|
h.Write([]byte(s))
|
|
return uint64(h.Sum32())
|
|
},
|
|
},
|
|
{
|
|
name: "FNV-1a",
|
|
digestBytes: func(b []byte) uint64 {
|
|
h := fnv.New64()
|
|
h.Write(b)
|
|
return h.Sum64()
|
|
},
|
|
digestString: func(s string) uint64 {
|
|
h := fnv.New64a()
|
|
h.Write([]byte(s))
|
|
return h.Sum64()
|
|
},
|
|
},
|
|
}
|
|
|
|
func BenchmarkHashes(b *testing.B) {
|
|
for _, bb := range benchmarks {
|
|
for _, benchSize := range []struct {
|
|
name string
|
|
n int
|
|
}{
|
|
{"5B", 5},
|
|
{"100B", 100},
|
|
{"4KB", 4e3},
|
|
{"10MB", 10e6},
|
|
} {
|
|
input := make([]byte, benchSize.n)
|
|
for i := range input {
|
|
input[i] = byte(i)
|
|
}
|
|
inputString := string(input)
|
|
if bb.directBytes != nil {
|
|
name := fmt.Sprintf("%s,direct,bytes,n=%s", bb.name, benchSize.name)
|
|
b.Run(name, func(b *testing.B) {
|
|
benchmarkHashBytes(b, input, bb.directBytes)
|
|
})
|
|
}
|
|
if bb.directString != nil {
|
|
name := fmt.Sprintf("%s,direct,string,n=%s", bb.name, benchSize.name)
|
|
b.Run(name, func(b *testing.B) {
|
|
benchmarkHashString(b, inputString, bb.directString)
|
|
})
|
|
}
|
|
if bb.digestBytes != nil {
|
|
name := fmt.Sprintf("%s,digest,bytes,n=%s", bb.name, benchSize.name)
|
|
b.Run(name, func(b *testing.B) {
|
|
benchmarkHashBytes(b, input, bb.digestBytes)
|
|
})
|
|
}
|
|
if bb.digestString != nil {
|
|
name := fmt.Sprintf("%s,digest,string,n=%s", bb.name, benchSize.name)
|
|
b.Run(name, func(b *testing.B) {
|
|
benchmarkHashString(b, inputString, bb.digestString)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func benchmarkHashBytes(b *testing.B, input []byte, fn func([]byte) uint64) {
|
|
b.SetBytes(int64(len(input)))
|
|
for i := 0; i < b.N; i++ {
|
|
sink = fn(input)
|
|
}
|
|
}
|
|
|
|
func benchmarkHashString(b *testing.B, input string, fn func(string) uint64) {
|
|
b.SetBytes(int64(len(input)))
|
|
for i := 0; i < b.N; i++ {
|
|
sink = fn(input)
|
|
}
|
|
}
|