s uint64
}
+// Bytes returns the hash of b with the given seed.
+//
+// Bytes is equivalent to, but more convenient and efficient than:
+//
+// var h Hash
+// h.SetSeed(seed)
+// h.Write(b)
+// return h.Sum()
+func Bytes(seed Seed, b []byte) uint64 {
+ state := seed.s
+ if state == 0 {
+ panic("maphash: use of uninitialized Seed")
+ }
+ if len(b) == 0 {
+ return rthash(nil, 0, state) // avoid &b[0] index panic below
+ }
+ if len(b) > bufSize {
+ b = b[:len(b):len(b)] // merge len and cap calculations when reslicing
+ for len(b) > bufSize {
+ state = rthash(&b[0], bufSize, state)
+ b = b[bufSize:]
+ }
+ }
+ return rthash(&b[0], len(b), state)
+}
+
+// String returns the hash of s with the given seed.
+//
+// String is equivalent to, but more convenient and efficient than:
+//
+// var h Hash
+// h.SetSeed(seed)
+// h.WriteString(s)
+// return h.Sum()
+func String(seed Seed, s string) uint64 {
+ state := seed.s
+ if state == 0 {
+ panic("maphash: use of uninitialized Seed")
+ }
+ for len(s) > bufSize {
+ p := (*byte)((*unsafeheader.String)(unsafe.Pointer(&s)).Data)
+ state = rthash(p, bufSize, state)
+ s = s[bufSize:]
+ }
+ p := (*byte)((*unsafeheader.String)(unsafe.Pointer(&s)).Data)
+ return rthash(p, len(s), state)
+}
+
// A Hash computes a seeded hash of a byte sequence.
//
// The zero Hash is a valid Hash ready to use.
import (
"bytes"
+ "fmt"
"hash"
"testing"
)
t.Errorf("hash %d not identical to a single Write", i)
}
}
+
+ if sum1 := Bytes(hh[0].Seed(), b); sum1 != hh[0].Sum64() {
+ t.Errorf("hash using Bytes not identical to a single Write")
+ }
+
+ if sum1 := String(hh[0].Seed(), string(b)); sum1 != hh[0].Sum64() {
+ t.Errorf("hash using String not identical to a single Write")
+ }
}
func TestHashBytesVsString(t *testing.T) {
func benchmarkSize(b *testing.B, size int) {
h := &Hash{}
buf := make([]byte, size)
- b.SetBytes(int64(size))
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
- h.Reset()
- h.Write(buf)
- h.Sum64()
- }
-}
-
-func BenchmarkHash8Bytes(b *testing.B) {
- benchmarkSize(b, 8)
-}
+ s := string(buf)
+
+ b.Run("Write", func(b *testing.B) {
+ b.SetBytes(int64(size))
+ for i := 0; i < b.N; i++ {
+ h.Reset()
+ h.Write(buf)
+ h.Sum64()
+ }
+ })
-func BenchmarkHash320Bytes(b *testing.B) {
- benchmarkSize(b, 320)
-}
+ b.Run("Bytes", func(b *testing.B) {
+ b.SetBytes(int64(size))
+ seed := h.Seed()
+ for i := 0; i < b.N; i++ {
+ Bytes(seed, buf)
+ }
+ })
-func BenchmarkHash1K(b *testing.B) {
- benchmarkSize(b, 1024)
+ b.Run("String", func(b *testing.B) {
+ b.SetBytes(int64(size))
+ seed := h.Seed()
+ for i := 0; i < b.N; i++ {
+ String(seed, s)
+ }
+ })
}
-func BenchmarkHash8K(b *testing.B) {
- benchmarkSize(b, 8192)
+func BenchmarkHash(b *testing.B) {
+ sizes := []int{4, 8, 16, 32, 64, 256, 320, 1024, 4096, 16384}
+ for _, size := range sizes {
+ b.Run(fmt.Sprint("n=", size), func(b *testing.B) {
+ benchmarkSize(b, size)
+ })
+ }
}