mirror of
https://github.com/golang/go
synced 2024-11-26 19:41:19 -07:00
runtime: using wyhash for memhashFallback on 32bit platform
wyhash is a general hash function that: 1. Default hash function of Zig, Nim 2. Passed Smhasher, BigCrush and PractRand 3. Less code 4. 3~26% faster than internal hashmap name old time/op new time/op delta Hash5 67.8ns ± 0% 65.4ns ± 0% -3.45% (p=0.000 n=7+10) Hash16 82.5ns ± 0% 74.2ns ± 0% -10.12% (p=0.000 n=6+8) Hash64 121ns ± 0% 102ns ± 0% -15.82% (p=0.000 n=7+10) Hash1024 1.13µs ± 0% 0.89µs ± 0% -20.58% (p=0.000 n=10+9) Hash65536 68.9µs ± 0% 54.4µs ± 0% -21.04% (p=0.000 n=10+7) HashStringSpeed 103ns ± 2% 93ns ± 3% -10.24% (p=0.000 n=9+10) HashBytesSpeed 191ns ± 2% 180ns ± 1% -5.40% (p=0.000 n=10+8) HashInt32Speed 59.0ns ± 2% 59.1ns ± 1% ~ (p=0.655 n=9+8) HashInt64Speed 72.7ns ± 3% 66.1ns ± 5% -9.04% (p=0.000 n=10+10) HashStringArraySpeed 270ns ± 1% 222ns ± 2% -17.91% (p=0.000 n=10+10) FastrandHashiter 108ns ± 0% 109ns ± 1% +0.96% (p=0.002 n=10+10) name old speed new speed delta Hash5 73.8MB/s ± 0% 76.4MB/s ± 0% +3.58% (p=0.000 n=7+10) Hash16 194MB/s ± 0% 216MB/s ± 0% +11.25% (p=0.000 n=10+8) Hash64 530MB/s ± 0% 630MB/s ± 0% +18.74% (p=0.000 n=8+10) Hash1024 910MB/s ± 0% 1145MB/s ± 0% +25.88% (p=0.000 n=10+9) Hash65536 951MB/s ± 0% 1204MB/s ± 0% +26.64% (p=0.000 n=10+7) Update #43130 Change-Id: Id00c54b116a2411fcf675e95896fffb85f0e25b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/280372 Trust: Meng Zhuo <mzh@golangcn.org> Run-TryBot: Meng Zhuo <mzh@golangcn.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
f02a26bed0
commit
78f9015236
@ -3,8 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Hashing algorithm inspired by
|
||||
// xxhash: https://code.google.com/p/xxhash/
|
||||
// cityhash: https://code.google.com/p/cityhash/
|
||||
// wyhash: https://github.com/wangyi-fudan/wyhash/blob/ceb019b530e2c1c14d70b79bfa2bc49de7d95bc1/Modern%20Non-Cryptographic%20Hash%20Function%20and%20Pseudorandom%20Number%20Generator.pdf
|
||||
|
||||
//go:build 386 || arm || mips || mipsle
|
||||
// +build 386 arm mips mipsle
|
||||
@ -13,101 +12,52 @@ package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
const (
|
||||
// Constants for multiplication: four random odd 32-bit numbers.
|
||||
m1 = 3168982561
|
||||
m2 = 3339683297
|
||||
m3 = 832293441
|
||||
m4 = 2336365089
|
||||
)
|
||||
|
||||
func memhashFallback(p unsafe.Pointer, seed, s uintptr) uintptr {
|
||||
h := uint32(seed + s*hashkey[0])
|
||||
tail:
|
||||
switch {
|
||||
case s == 0:
|
||||
case s < 4:
|
||||
h ^= uint32(*(*byte)(p))
|
||||
h ^= uint32(*(*byte)(add(p, s>>1))) << 8
|
||||
h ^= uint32(*(*byte)(add(p, s-1))) << 16
|
||||
h = rotl_15(h*m1) * m2
|
||||
case s == 4:
|
||||
h ^= readUnaligned32(p)
|
||||
h = rotl_15(h*m1) * m2
|
||||
case s <= 8:
|
||||
h ^= readUnaligned32(p)
|
||||
h = rotl_15(h*m1) * m2
|
||||
h ^= readUnaligned32(add(p, s-4))
|
||||
h = rotl_15(h*m1) * m2
|
||||
case s <= 16:
|
||||
h ^= readUnaligned32(p)
|
||||
h = rotl_15(h*m1) * m2
|
||||
h ^= readUnaligned32(add(p, 4))
|
||||
h = rotl_15(h*m1) * m2
|
||||
h ^= readUnaligned32(add(p, s-8))
|
||||
h = rotl_15(h*m1) * m2
|
||||
h ^= readUnaligned32(add(p, s-4))
|
||||
h = rotl_15(h*m1) * m2
|
||||
default:
|
||||
v1 := h
|
||||
v2 := uint32(seed * hashkey[1])
|
||||
v3 := uint32(seed * hashkey[2])
|
||||
v4 := uint32(seed * hashkey[3])
|
||||
for s >= 16 {
|
||||
v1 ^= readUnaligned32(p)
|
||||
v1 = rotl_15(v1*m1) * m2
|
||||
p = add(p, 4)
|
||||
v2 ^= readUnaligned32(p)
|
||||
v2 = rotl_15(v2*m2) * m3
|
||||
p = add(p, 4)
|
||||
v3 ^= readUnaligned32(p)
|
||||
v3 = rotl_15(v3*m3) * m4
|
||||
p = add(p, 4)
|
||||
v4 ^= readUnaligned32(p)
|
||||
v4 = rotl_15(v4*m4) * m1
|
||||
p = add(p, 4)
|
||||
s -= 16
|
||||
}
|
||||
h = v1 ^ v2 ^ v3 ^ v4
|
||||
goto tail
|
||||
}
|
||||
h ^= h >> 17
|
||||
h *= m3
|
||||
h ^= h >> 13
|
||||
h *= m4
|
||||
h ^= h >> 16
|
||||
return uintptr(h)
|
||||
}
|
||||
|
||||
func memhash32Fallback(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)
|
||||
a, b := mix32(uint32(seed), uint32(4^hashkey[0]))
|
||||
t := readUnaligned32(p)
|
||||
a ^= t
|
||||
b ^= t
|
||||
a, b = mix32(a, b)
|
||||
a, b = mix32(a, b)
|
||||
return uintptr(a ^ b)
|
||||
}
|
||||
|
||||
func memhash64Fallback(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)
|
||||
a, b := mix32(uint32(seed), uint32(8^hashkey[0]))
|
||||
a ^= readUnaligned32(p)
|
||||
b ^= readUnaligned32(add(p, 4))
|
||||
a, b = mix32(a, b)
|
||||
a, b = mix32(a, b)
|
||||
return uintptr(a ^ b)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func rotl_15(x uint32) uint32 {
|
||||
return (x << 15) | (x >> (32 - 15))
|
||||
func memhashFallback(p unsafe.Pointer, seed, s uintptr) uintptr {
|
||||
|
||||
a, b := mix32(uint32(seed), uint32(s^hashkey[0]))
|
||||
if s == 0 {
|
||||
return uintptr(a ^ b)
|
||||
}
|
||||
for ; s > 8; s -= 8 {
|
||||
a ^= readUnaligned32(p)
|
||||
b ^= readUnaligned32(add(p, 4))
|
||||
a, b = mix32(a, b)
|
||||
p = add(p, 8)
|
||||
}
|
||||
if s >= 4 {
|
||||
a ^= readUnaligned32(p)
|
||||
b ^= readUnaligned32(add(p, s-4))
|
||||
} else {
|
||||
t := uint32(*(*byte)(p))
|
||||
t |= uint32(*(*byte)(add(p, s>>1))) << 8
|
||||
t |= uint32(*(*byte)(add(p, s-1))) << 16
|
||||
b ^= t
|
||||
}
|
||||
a, b = mix32(a, b)
|
||||
a, b = mix32(a, b)
|
||||
return uintptr(a ^ b)
|
||||
}
|
||||
|
||||
func mix32(a, b uint32) (uint32, uint32) {
|
||||
c := uint64(a^uint32(hashkey[1])) * uint64(b^uint32(hashkey[2]))
|
||||
return uint32(c), uint32(c >> 32)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user