internal/runtime/maps: don't hash twice when deleting

│  baseline   │             experiment              │
                     │   sec/op    │   sec/op     vs base                │
MapDeleteLargeKey-24   312.0n ± 6%   162.3n ± 5%  -47.97% (p=0.000 n=10)

Change-Id: I31f1f8e3c344cf8abf2e9eb4b51b78fcd67b93c4
Reviewed-on: https://go-review.googlesource.com/c/go/+/625906
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Keith Randall 2024-11-09 09:53:09 -08:00
parent f9159b11e5
commit 4c8ab993cd
3 changed files with 13 additions and 4 deletions

View File

@ -663,7 +663,7 @@ func (m *Map) Delete(typ *abi.SwissMapType, key unsafe.Pointer) {
m.deleteSmall(typ, hash, key)
} else {
idx := m.directoryIndex(hash)
m.directoryAt(idx).Delete(typ, m, key)
m.directoryAt(idx).Delete(typ, m, hash, key)
}
if m.used == 0 {

View File

@ -409,9 +409,7 @@ func (t *table) uncheckedPutSlot(typ *abi.SwissMapType, hash uintptr, key unsafe
}
}
func (t *table) Delete(typ *abi.SwissMapType, m *Map, key unsafe.Pointer) {
hash := typ.Hasher(key, m.seed)
func (t *table) Delete(typ *abi.SwissMapType, m *Map, hash uintptr, key unsafe.Pointer) {
seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
for ; ; seq = seq.next() {
g := t.groups.group(typ, seq.offset)

View File

@ -1090,3 +1090,14 @@ func BenchmarkMapPop(b *testing.B) {
b.Run("Key=*int32/Elem=int32", benchSizes(benchmarkMapPop[*int32, int32]))
b.Run("Key=int32/Elem=*int32", benchSizes(benchmarkMapPop[int32, *int32]))
}
func BenchmarkMapDeleteLargeKey(b *testing.B) {
m := map[string]int{}
for i := range 9 {
m[fmt.Sprintf("%d", i)] = i
}
key := strings.Repeat("*", 10000)
for range b.N {
delete(m, key)
}
}