]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: specialize memhash32 and memhash64
authorMartin Möhrmann <moehrmann@google.com>
Sun, 27 Aug 2017 12:05:11 +0000 (14:05 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Mon, 28 Aug 2017 19:55:27 +0000 (19:55 +0000)
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: Keith Randall <khr@golang.org>
src/runtime/alg.go
src/runtime/export_test.go
src/runtime/hash32.go
src/runtime/hash64.go
src/runtime/hash_test.go

index b90142814f0287251953a5719d3299b736969a23..89125f48ba7da589862341c64f4f40d94438f965 100644 (file)
@@ -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)
 }
index c929bd46187a89687f761638bc858832242a83b8..b99ee83e3e2042a103fcff4f92a738ae3d06e417 100644 (file)
@@ -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))
index be59076635ae6fe7119a222c23bbcfda3e51bcb5..5574923911e3779b83cd3eade1e643a28e19ba13 100644 (file)
@@ -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.
index d61f114475aa9887793ce2bd83451b4cf178bcfe..22085d3df074c202c280501eead203c02f8e2a5a 100644 (file)
@@ -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.
index a6f3cdbdbe4f638fe82115e9cd68629697bccd45..1400579cda8b89e98ffb43000b3085ecbb475321 100644 (file)
@@ -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.