Skip to content

Commit 2a56b02

Browse files
committed
runtime: specialize memhash32 and memhash64
AMD64 with AES support disabled: name old time/op new time/op delta MapPopulate/1 78.0ns ± 1% 75.5ns ± 1% -3.17% (p=0.000 n=10+9) MapPopulate/10 764ns ± 2% 673ns ± 2% -11.91% (p=0.000 n=10+10) MapPopulate/100 9.52µs ± 1% 8.54µs ± 1% -10.37% (p=0.000 n=8+10) MapPopulate/1000 116µs ± 2% 103µs ± 1% -10.40% (p=0.000 n=10+8) MapPopulate/10000 1.01ms ± 1% 0.90ms ± 1% -10.70% (p=0.000 n=10+10) MapPopulate/100000 9.81ms ± 1% 8.67ms ± 2% -11.54% (p=0.000 n=10+10) 386 with AES support disabled: name old time/op new time/op delta MapPopulate/1 95.3ns ± 1% 90.6ns ± 1% -4.95% (p=0.000 n=10+9) MapPopulate/10 983ns ± 2% 912ns ± 1% -7.18% (p=0.000 n=10+10) MapPopulate/100 11.9µs ± 2% 11.2µs ± 1% -6.01% (p=0.000 n=10+10) MapPopulate/1000 140µs ± 1% 131µs ± 1% -6.19% (p=0.000 n=10+10) MapPopulate/10000 1.26ms ± 2% 1.18ms ± 1% -5.93% (p=0.000 n=9+10) MapPopulate/100000 12.1ms ± 2% 11.4ms ± 1% -5.48% (p=0.000 n=10+10) Fixes #21539 Change-Id: Ice128c947c9a6a294800d6a5250d82045eb70b55 Reviewed-on: https://go-review.googlesource.com/59352 Run-TryBot: Martin Möhrmann <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent 75d7a02 commit 2a56b02

File tree

5 files changed

+98
-12
lines changed

5 files changed

+98
-12
lines changed

src/runtime/alg.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,15 @@ type typeAlg struct {
4747
func memhash0(p unsafe.Pointer, h uintptr) uintptr {
4848
return h
4949
}
50+
5051
func memhash8(p unsafe.Pointer, h uintptr) uintptr {
5152
return memhash(p, h, 1)
5253
}
54+
5355
func memhash16(p unsafe.Pointer, h uintptr) uintptr {
5456
return memhash(p, h, 2)
5557
}
56-
func memhash32(p unsafe.Pointer, h uintptr) uintptr {
57-
return memhash(p, h, 4)
58-
}
59-
func memhash64(p unsafe.Pointer, h uintptr) uintptr {
60-
return memhash(p, h, 8)
61-
}
58+
6259
func memhash128(p unsafe.Pointer, h uintptr) uintptr {
6360
return memhash(p, h, 16)
6461
}

src/runtime/export_test.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,19 @@ func RunSchedLocalQueueEmptyTest(iters int) {
152152
}
153153
}
154154

155-
var StringHash = stringHash
156-
var BytesHash = bytesHash
157-
var Int32Hash = int32Hash
158-
var Int64Hash = int64Hash
159-
var EfaceHash = efaceHash
160-
var IfaceHash = ifaceHash
155+
var (
156+
StringHash = stringHash
157+
BytesHash = bytesHash
158+
Int32Hash = int32Hash
159+
Int64Hash = int64Hash
160+
MemHash = memhash
161+
MemHash32 = memhash32
162+
MemHash64 = memhash64
163+
EfaceHash = efaceHash
164+
IfaceHash = ifaceHash
165+
)
166+
167+
var UseAeshash = &useAeshash
161168

162169
func MemclrBytes(b []byte) {
163170
s := (*slice)(unsafe.Pointer(&b))

src/runtime/hash32.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,32 @@ tail:
8181
return uintptr(h)
8282
}
8383

84+
func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
85+
h := uint32(seed + 4*hashkey[0])
86+
h ^= readUnaligned32(p)
87+
h = rotl_15(h*m1) * m2
88+
h ^= h >> 17
89+
h *= m3
90+
h ^= h >> 13
91+
h *= m4
92+
h ^= h >> 16
93+
return uintptr(h)
94+
}
95+
96+
func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
97+
h := uint32(seed + 8*hashkey[0])
98+
h ^= readUnaligned32(p)
99+
h = rotl_15(h*m1) * m2
100+
h ^= readUnaligned32(add(p, 4))
101+
h = rotl_15(h*m1) * m2
102+
h ^= h >> 17
103+
h *= m3
104+
h ^= h >> 13
105+
h *= m4
106+
h ^= h >> 16
107+
return uintptr(h)
108+
}
109+
84110
// Note: in order to get the compiler to issue rotl instructions, we
85111
// need to constant fold the shift amount by hand.
86112
// TODO: convince the compiler to issue rotl instructions after inlining.

src/runtime/hash64.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@ tail:
8181
return uintptr(h)
8282
}
8383

84+
func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
85+
h := uint64(seed + 4*hashkey[0])
86+
v := uint64(readUnaligned32(p))
87+
h ^= v
88+
h ^= v << 32
89+
h = rotl_31(h*m1) * m2
90+
h ^= h >> 29
91+
h *= m3
92+
h ^= h >> 32
93+
return uintptr(h)
94+
}
95+
96+
func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
97+
h := uint64(seed + 8*hashkey[0])
98+
h ^= readUnaligned64(p)
99+
h = rotl_31(h*m1) * m2
100+
h ^= h >> 29
101+
h *= m3
102+
h ^= h >> 32
103+
return uintptr(h)
104+
}
105+
84106
// Note: in order to get the compiler to issue rotl instructions, we
85107
// need to constant fold the shift amount by hand.
86108
// TODO: convince the compiler to issue rotl instructions after inlining.

src/runtime/hash_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,40 @@ import (
1414
"unsafe"
1515
)
1616

17+
func TestMemHash32Equality(t *testing.T) {
18+
if *UseAeshash {
19+
t.Skip("skipping since AES hash implementation is used")
20+
}
21+
var b [4]byte
22+
r := rand.New(rand.NewSource(1234))
23+
seed := uintptr(r.Uint64())
24+
for i := 0; i < 100; i++ {
25+
randBytes(r, b[:])
26+
got := MemHash32(unsafe.Pointer(&b), seed)
27+
want := MemHash(unsafe.Pointer(&b), seed, 4)
28+
if got != want {
29+
t.Errorf("MemHash32(%x, %v) = %v; want %v", b, seed, got, want)
30+
}
31+
}
32+
}
33+
34+
func TestMemHash64Equality(t *testing.T) {
35+
if *UseAeshash {
36+
t.Skip("skipping since AES hash implementation is used")
37+
}
38+
var b [8]byte
39+
r := rand.New(rand.NewSource(1234))
40+
seed := uintptr(r.Uint64())
41+
for i := 0; i < 100; i++ {
42+
randBytes(r, b[:])
43+
got := MemHash64(unsafe.Pointer(&b), seed)
44+
want := MemHash(unsafe.Pointer(&b), seed, 8)
45+
if got != want {
46+
t.Errorf("MemHash64(%x, %v) = %v; want %v", b, seed, got, want)
47+
}
48+
}
49+
}
50+
1751
// Smhasher is a torture test for hash functions.
1852
// https://code.google.com/p/smhasher/
1953
// This code is a port of some of the Smhasher tests to Go.

0 commit comments

Comments
 (0)