1 package xxhash
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "hash"
8 "hash/crc32"
9 "strings"
10 "testing"
11
12 OneOfOne "github.com/OneOfOne/xxhash"
13 "github.com/spaolacci/murmur3"
14 )
15
16 var result uint64
17
18 func BenchmarkStringHash(b *testing.B) {
19 const s = "abcdefghijklmnop"
20 var r uint64
21 b.ReportAllocs()
22 for n := 0; n < b.N; n++ {
23 r = Sum64([]byte(s))
24 }
25 result = r
26 }
27
28 func TestSum(t *testing.T) {
29 for i, tt := range []struct {
30 input string
31 want uint64
32 }{
33 {"", 0xef46db3751d8e999},
34 {"a", 0xd24ec4f1a98c6e5b},
35 {"as", 0x1c330fb2d66be179},
36 {"asd", 0x631c37ce72a97393},
37 {"asdf", 0x415872f599cea71e},
38 {
39
40 "Call me Ishmael. Some years ago--never mind how long precisely-",
41 0x02a2e85470d6fd96,
42 },
43 } {
44 for chunkSize := 1; chunkSize <= len(tt.input); chunkSize++ {
45 x := New()
46 for j := 0; j < len(tt.input); j += chunkSize {
47 end := j + chunkSize
48 if end > len(tt.input) {
49 end = len(tt.input)
50 }
51 chunk := []byte(tt.input[j:end])
52 n, err := x.Write(chunk)
53 if err != nil || n != len(chunk) {
54 t.Fatalf("[i=%d,chunkSize=%d] Write: got (%d, %v); want (%d, nil)",
55 i, chunkSize, n, err, len(chunk))
56 }
57 }
58 if got := x.Sum64(); got != tt.want {
59 t.Fatalf("[i=%d,chunkSize=%d] got 0x%x; want 0x%x",
60 i, chunkSize, got, tt.want)
61 }
62 var b [8]byte
63 binary.BigEndian.PutUint64(b[:], tt.want)
64 if got := x.Sum(nil); !bytes.Equal(got, b[:]) {
65 t.Fatalf("[i=%d,chunkSize=%d] Sum: got %v; want %v",
66 i, chunkSize, got, b[:])
67 }
68 }
69 if got := Sum64([]byte(tt.input)); got != tt.want {
70 t.Fatalf("[i=%d] Sum64: got 0x%x; want 0x%x", i, got, tt.want)
71 }
72 if got := Sum64String(tt.input); got != tt.want {
73 t.Fatalf("[i=%d] Sum64String: got 0x%x; want 0x%x", i, got, tt.want)
74 }
75 }
76 }
77
78 func TestReset(t *testing.T) {
79 parts := []string{"The quic", "k br", "o", "wn fox jumps", " ov", "er the lazy ", "dog."}
80 x := New()
81 for _, part := range parts {
82 x.Write([]byte(part))
83 }
84 h0 := x.Sum64()
85
86 x.Reset()
87 x.Write([]byte(strings.Join(parts, "")))
88 h1 := x.Sum64()
89
90 if h0 != h1 {
91 t.Errorf("0x%x != 0x%x", h0, h1)
92 }
93 }
94
95 var (
96 sink uint64
97 sinkb []byte
98 )
99
100 func sumFunc(h hash.Hash) func(b []byte) uint64 {
101 return func(b []byte) uint64 {
102 h.Reset()
103 h.Write(b)
104 sinkb = h.Sum(nil)
105 return 0
106 }
107 }
108
109 func BenchmarkHashes(b *testing.B) {
110 for _, ht := range []struct {
111 name string
112 f interface{}
113 }{
114 {"xxhash", Sum64},
115 {"xxhash-string", Sum64String},
116 {"OneOfOne", OneOfOne.Checksum64},
117 {"murmur3", murmur3.Sum64},
118 {"CRC-32", sumFunc(crc32.NewIEEE())},
119 } {
120 for _, nt := range []struct {
121 name string
122 n int
123 }{
124 {"5 B", 5},
125 {"100 B", 100},
126 {"4 KB", 4e3},
127 {"10 MB", 10e6},
128 } {
129 input := make([]byte, nt.n)
130 for i := range input {
131 input[i] = byte(i)
132 }
133 benchName := fmt.Sprintf("%s,n=%s", ht.name, nt.name)
134 if ht.name == "xxhash-string" {
135 f := ht.f.(func(string) uint64)
136 s := string(input)
137 b.Run(benchName, func(b *testing.B) {
138 b.SetBytes(int64(len(input)))
139 for i := 0; i < b.N; i++ {
140 sink = f(s)
141 }
142 })
143 } else {
144 f := ht.f.(func([]byte) uint64)
145 b.Run(benchName, func(b *testing.B) {
146 b.SetBytes(int64(len(input)))
147 for i := 0; i < b.N; i++ {
148 sink = f(input)
149 }
150 })
151 }
152 }
153 }
154 }
155
View as plain text