From 8a85a2e70a97773ac96e899df7411eda4f5da2cb Mon Sep 17 00:00:00 2001 From: Mateusz Poliwczak Date: Mon, 7 Apr 2025 15:21:16 +0200 Subject: runtime, internal/runtime/maps: speed-up empty/zero map lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets the inliner do a better job optimizing the mapKeyError call. goos: linux goarch: amd64 pkg: runtime cpu: AMD Ryzen 5 4600G with Radeon Graphics │ /tmp/before2 │ /tmp/after3 │ │ sec/op │ sec/op vs base │ MapAccessZero/Key=int64-12 1.875n ± 0% 1.875n ± 0% ~ (p=0.506 n=25) MapAccessZero/Key=int32-12 1.875n ± 0% 1.875n ± 0% ~ (p=0.082 n=25) MapAccessZero/Key=string-12 1.902n ± 1% 1.902n ± 1% ~ (p=0.256 n=25) MapAccessZero/Key=mediumType-12 2.816n ± 0% 1.958n ± 0% -30.47% (p=0.000 n=25) MapAccessZero/Key=bigType-12 2.815n ± 0% 1.935n ± 0% -31.26% (p=0.000 n=25) MapAccessEmpty/Key=int64-12 1.942n ± 0% 2.109n ± 0% +8.60% (p=0.000 n=25) MapAccessEmpty/Key=int32-12 2.110n ± 0% 1.940n ± 0% -8.06% (p=0.000 n=25) MapAccessEmpty/Key=string-12 2.024n ± 0% 2.109n ± 0% +4.20% (p=0.000 n=25) MapAccessEmpty/Key=mediumType-12 3.157n ± 0% 2.344n ± 0% -25.75% (p=0.000 n=25) MapAccessEmpty/Key=bigType-12 3.054n ± 0% 2.115n ± 0% -30.75% (p=0.000 n=25) geomean 2.305n 2.011n -12.75% Change-Id: Iee83930884dc4c8a791a711aa189a1c93b68d536 Reviewed-on: https://go-review.googlesource.com/c/go/+/663495 Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt --- src/runtime/alg.go | 68 ------------------------------------------------------ 1 file changed, 68 deletions(-) (limited to 'src/runtime/alg.go') diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 4626899aaf..df32bc7941 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -250,74 +250,6 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { } } -func mapKeyError(t *maptype, p unsafe.Pointer) error { - if !t.HashMightPanic() { - return nil - } - return mapKeyError2(t.Key, p) -} - -func mapKeyError2(t *_type, p unsafe.Pointer) error { - if t.TFlag&abi.TFlagRegularMemory != 0 { - return nil - } - switch t.Kind_ & abi.KindMask { - case abi.Float32, abi.Float64, abi.Complex64, abi.Complex128, abi.String: - return nil - case abi.Interface: - i := (*interfacetype)(unsafe.Pointer(t)) - var t *_type - var pdata *unsafe.Pointer - if len(i.Methods) == 0 { - a := (*eface)(p) - t = a._type - if t == nil { - return nil - } - pdata = &a.data - } else { - a := (*iface)(p) - if a.tab == nil { - return nil - } - t = a.tab.Type - pdata = &a.data - } - - if t.Equal == nil { - return errorString("hash of unhashable type " + toRType(t).string()) - } - - if isDirectIface(t) { - return mapKeyError2(t, unsafe.Pointer(pdata)) - } else { - return mapKeyError2(t, *pdata) - } - case abi.Array: - a := (*arraytype)(unsafe.Pointer(t)) - for i := uintptr(0); i < a.Len; i++ { - if err := mapKeyError2(a.Elem, add(p, i*a.Elem.Size_)); err != nil { - return err - } - } - return nil - case abi.Struct: - s := (*structtype)(unsafe.Pointer(t)) - for _, f := range s.Fields { - if f.Name.IsBlank() { - continue - } - if err := mapKeyError2(f.Typ, add(p, f.Offset)); err != nil { - return err - } - } - return nil - default: - // Should never happen, keep this case for robustness. - return errorString("hash of unhashable type " + toRType(t).string()) - } -} - //go:linkname reflect_typehash reflect.typehash func reflect_typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { return typehash(t, p, h) -- cgit v1.3-5-g9baa