From d13e6d0b089b72d666d0dd46f4965660ab10b712 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 18 Nov 2024 16:37:59 -0800 Subject: [PATCH] internal/runtime/maps: hash copy of key instead of key itself Hashing the key means we have to take the address of it. That inhibits subsequent optimizations on the key variable. By hashing a copy, we incur an extra store at the hash callsite, but we no longer need a load of the key in the inner loop. It can live in a register throughout. (Technically, it gets spilled around the call to the hasher, but it gets restored outside the loop.) Maybe one day we can have special hash functions that take int64/int32/string instead of *int64/*int32/*string. Change-Id: Iba3133f6e82328f53c0abcb5eec13ee47c4969d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/629419 Reviewed-by: Russ Cox LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt --- src/internal/runtime/maps/runtime_fast32_swiss.go | 12 ++++++++---- src/internal/runtime/maps/runtime_fast64_swiss.go | 12 ++++++++---- src/internal/runtime/maps/runtime_faststr_swiss.go | 9 ++++++--- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/internal/runtime/maps/runtime_fast32_swiss.go b/src/internal/runtime/maps/runtime_fast32_swiss.go index ff5815abdd1..15facbfe8a6 100644 --- a/src/internal/runtime/maps/runtime_fast32_swiss.go +++ b/src/internal/runtime/maps/runtime_fast32_swiss.go @@ -48,7 +48,8 @@ func runtime_mapaccess1_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe return unsafe.Pointer(&zeroVal[0]) } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -116,7 +117,8 @@ func runtime_mapaccess2_fast32(typ *abi.SwissMapType, m *Map, key uint32) (unsaf return unsafe.Pointer(&zeroVal[0]), false } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -203,7 +205,8 @@ func runtime_mapassign_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe. fatal("concurrent map writes") } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Set writing after calling Hasher, since Hasher may panic, in which // case we have not actually done a write. @@ -336,7 +339,8 @@ func runtime_mapassign_fast32ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point fatal("concurrent map writes") } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Set writing after calling Hasher, since Hasher may panic, in which // case we have not actually done a write. diff --git a/src/internal/runtime/maps/runtime_fast64_swiss.go b/src/internal/runtime/maps/runtime_fast64_swiss.go index 90e84f83d25..f08e7ef8690 100644 --- a/src/internal/runtime/maps/runtime_fast64_swiss.go +++ b/src/internal/runtime/maps/runtime_fast64_swiss.go @@ -48,7 +48,8 @@ func runtime_mapaccess1_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe return unsafe.Pointer(&zeroVal[0]) } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -116,7 +117,8 @@ func runtime_mapaccess2_fast64(typ *abi.SwissMapType, m *Map, key uint64) (unsaf return unsafe.Pointer(&zeroVal[0]), false } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -203,7 +205,8 @@ func runtime_mapassign_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe. fatal("concurrent map writes") } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Set writing after calling Hasher, since Hasher may panic, in which // case we have not actually done a write. @@ -374,7 +377,8 @@ func runtime_mapassign_fast64ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point fatal("concurrent map writes") } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Set writing after calling Hasher, since Hasher may panic, in which // case we have not actually done a write. diff --git a/src/internal/runtime/maps/runtime_faststr_swiss.go b/src/internal/runtime/maps/runtime_faststr_swiss.go index a104945501d..077c05ae8b9 100644 --- a/src/internal/runtime/maps/runtime_faststr_swiss.go +++ b/src/internal/runtime/maps/runtime_faststr_swiss.go @@ -124,7 +124,8 @@ func runtime_mapaccess1_faststr(typ *abi.SwissMapType, m *Map, key string) unsaf return elem } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -182,7 +183,8 @@ func runtime_mapaccess2_faststr(typ *abi.SwissMapType, m *Map, key string) (unsa return elem, true } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Select table. idx := m.directoryIndex(hash) @@ -271,7 +273,8 @@ func runtime_mapassign_faststr(typ *abi.SwissMapType, m *Map, key string) unsafe fatal("concurrent map writes") } - hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed) + k := key + hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed) // Set writing after calling Hasher, since Hasher may panic, in which // case we have not actually done a write.