Commit 2a56b023 authored by Martin Möhrmann's avatar Martin Möhrmann

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 <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent 75d7a02e
......@@ -47,18 +47,15 @@ type typeAlg struct {
func memhash0(p unsafe.Pointer, h uintptr) uintptr {
return h
}
func memhash8(p unsafe.Pointer, h uintptr) uintptr {
return memhash(p, h, 1)
}
func memhash16(p unsafe.Pointer, h uintptr) uintptr {
return memhash(p, h, 2)
}
func memhash32(p unsafe.Pointer, h uintptr) uintptr {
return memhash(p, h, 4)
}
func memhash64(p unsafe.Pointer, h uintptr) uintptr {
return memhash(p, h, 8)
}
func memhash128(p unsafe.Pointer, h uintptr) uintptr {
return memhash(p, h, 16)
}
......
......@@ -152,12 +152,19 @@ func RunSchedLocalQueueEmptyTest(iters int) {
}
}
var StringHash = stringHash
var BytesHash = bytesHash
var Int32Hash = int32Hash
var Int64Hash = int64Hash
var EfaceHash = efaceHash
var IfaceHash = ifaceHash
var (
StringHash = stringHash
BytesHash = bytesHash
Int32Hash = int32Hash
Int64Hash = int64Hash
MemHash = memhash
MemHash32 = memhash32
MemHash64 = memhash64
EfaceHash = efaceHash
IfaceHash = ifaceHash
)
var UseAeshash = &useAeshash
func MemclrBytes(b []byte) {
s := (*slice)(unsafe.Pointer(&b))
......
......@@ -81,6 +81,32 @@ tail:
return uintptr(h)
}
func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
h := uint32(seed + 4*hashkey[0])
h ^= readUnaligned32(p)
h = rotl_15(h*m1) * m2
h ^= h >> 17
h *= m3
h ^= h >> 13
h *= m4
h ^= h >> 16
return uintptr(h)
}
func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
h := uint32(seed + 8*hashkey[0])
h ^= readUnaligned32(p)
h = rotl_15(h*m1) * m2
h ^= readUnaligned32(add(p, 4))
h = rotl_15(h*m1) * m2
h ^= h >> 17
h *= m3
h ^= h >> 13
h *= m4
h ^= h >> 16
return uintptr(h)
}
// Note: in order to get the compiler to issue rotl instructions, we
// need to constant fold the shift amount by hand.
// TODO: convince the compiler to issue rotl instructions after inlining.
......
......@@ -81,6 +81,28 @@ tail:
return uintptr(h)
}
func memhash32(p unsafe.Pointer, seed uintptr) uintptr {
h := uint64(seed + 4*hashkey[0])
v := uint64(readUnaligned32(p))
h ^= v
h ^= v << 32
h = rotl_31(h*m1) * m2
h ^= h >> 29
h *= m3
h ^= h >> 32
return uintptr(h)
}
func memhash64(p unsafe.Pointer, seed uintptr) uintptr {
h := uint64(seed + 8*hashkey[0])
h ^= readUnaligned64(p)
h = rotl_31(h*m1) * m2
h ^= h >> 29
h *= m3
h ^= h >> 32
return uintptr(h)
}
// Note: in order to get the compiler to issue rotl instructions, we
// need to constant fold the shift amount by hand.
// TODO: convince the compiler to issue rotl instructions after inlining.
......
......@@ -14,6 +14,40 @@ import (
"unsafe"
)
func TestMemHash32Equality(t *testing.T) {
if *UseAeshash {
t.Skip("skipping since AES hash implementation is used")
}
var b [4]byte
r := rand.New(rand.NewSource(1234))
seed := uintptr(r.Uint64())
for i := 0; i < 100; i++ {
randBytes(r, b[:])
got := MemHash32(unsafe.Pointer(&b), seed)
want := MemHash(unsafe.Pointer(&b), seed, 4)
if got != want {
t.Errorf("MemHash32(%x, %v) = %v; want %v", b, seed, got, want)
}
}
}
func TestMemHash64Equality(t *testing.T) {
if *UseAeshash {
t.Skip("skipping since AES hash implementation is used")
}
var b [8]byte
r := rand.New(rand.NewSource(1234))
seed := uintptr(r.Uint64())
for i := 0; i < 100; i++ {
randBytes(r, b[:])
got := MemHash64(unsafe.Pointer(&b), seed)
want := MemHash(unsafe.Pointer(&b), seed, 8)
if got != want {
t.Errorf("MemHash64(%x, %v) = %v; want %v", b, seed, got, want)
}
}
}
// Smhasher is a torture test for hash functions.
// https://code.google.com/p/smhasher/
// This code is a port of some of the Smhasher tests to Go.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment