aboutsummaryrefslogtreecommitdiff
path: root/src/internal/runtime
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2025-10-24 12:04:44 -0400
committerCherry Mui <cherryyz@google.com>2025-10-24 12:40:49 -0700
commita26f860fa4fee16f77e0ed13eb8286168b3bf097 (patch)
treed5aae44cd02487888d4e3c68e505e7217c8a311a /src/internal/runtime
parent747fe2efedfdc43f797b4fc1672e29ff7a01ec6a (diff)
downloadgo-a26f860fa4fee16f77e0ed13eb8286168b3bf097.tar.xz
runtime: use 32-bit hash for maps on Wasm
Currently we use 64-bit hash calculations on Wasm. The 64-bit hash calculation make intensive uses of 64x64->128 bit multiplications, which on many 64-bit platforms are compiler intrinsics and can be compiled to one or two instructions. This is not the case on Wasm, so it is not very performant. This CL makes it use 32-bit hashes on Wasm, just like other 32-bit architectures. The 32-bit hash calculation only uses 32x32->64 bit multiplications, which can be compiled efficiently on Wasm. Using 32-bit hashes may increase the chance of collisions. But it is the same as 32-bit architectures like 386. And our Wasm port supports only 32-bit address space (like 386), so this is not too bad. Runtime Hash benchmark results goos: js goarch: wasm pkg: runtime │ 0h.txt │ 1h.txt │ │ sec/op │ sec/op vs base │ Hash5 20.45n ± 9% 14.06n ± 2% -31.21% (p=0.000 n=10) Hash16 22.34n ± 7% 17.52n ± 1% -21.62% (p=0.000 n=10) Hash64 47.47n ± 3% 28.68n ± 1% -39.59% (p=0.000 n=10) Hash1024 475.4n ± 1% 271.4n ± 0% -42.92% (p=0.000 n=10) Hash65536 28.42µ ± 1% 16.66µ ± 0% -41.40% (p=0.000 n=10) HashStringSpeed 40.07n ± 7% 29.23n ± 1% -27.05% (p=0.000 n=10) HashBytesSpeed 62.01n ± 3% 46.11n ± 4% -25.64% (p=0.000 n=10) HashInt32Speed 24.31n ± 2% 20.39n ± 1% -16.13% (p=0.000 n=10) HashInt64Speed 25.48n ± 7% 20.81n ± 7% -18.29% (p=0.000 n=10) HashStringArraySpeed 87.69n ± 4% 76.65n ± 2% -12.58% (p=0.000 n=10) FastrandHashiter 87.65n ± 1% 87.65n ± 1% ~ (p=0.896 n=10) geomean 90.82n 67.03n -26.19% Map benchmarks are too many to post here. The speedups are around 0-40%. Change-Id: I2f7a68cfc446ab5a547fdb6a40aea07854516d51 Reviewed-on: https://go-review.googlesource.com/c/go/+/714600 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/internal/runtime')
-rw-r--r--src/internal/runtime/maps/map.go6
-rw-r--r--src/internal/runtime/maps/table.go3
2 files changed, 6 insertions, 3 deletions
diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go
index 865a3f36c2..515558a94f 100644
--- a/src/internal/runtime/maps/map.go
+++ b/src/internal/runtime/maps/map.go
@@ -245,8 +245,12 @@ type Map struct {
clearSeq uint64
}
+// Use 64-bit hash on 64-bit systems, except on Wasm, where we use
+// 32-bit hash (see runtime/hash32.go).
+const Use64BitHash = goarch.PtrSize == 8 && goarch.IsWasm == 0
+
func depthToShift(depth uint8) uint8 {
- if goarch.PtrSize == 4 {
+ if !Use64BitHash {
return 32 - depth
}
return 64 - depth
diff --git a/src/internal/runtime/maps/table.go b/src/internal/runtime/maps/table.go
index d9bcf23dfa..fbce099655 100644
--- a/src/internal/runtime/maps/table.go
+++ b/src/internal/runtime/maps/table.go
@@ -6,7 +6,6 @@ package maps
import (
"internal/abi"
- "internal/goarch"
"internal/runtime/math"
"unsafe"
)
@@ -1170,7 +1169,7 @@ func (t *table) rehash(typ *abi.MapType, m *Map) {
// Bitmask for the last selection bit at this depth.
func localDepthMask(localDepth uint8) uintptr {
- if goarch.PtrSize == 4 {
+ if !Use64BitHash {
return uintptr(1) << (32 - localDepth)
}
return uintptr(1) << (64 - localDepth)