From 630ef2edc2a7f6138c9eb0ed8eb8216a32ed0339 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 1 May 2023 12:54:27 -0400 Subject: [PATCH] cmd/link: remove allocation in decoding type name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The type name symbol is always from a Go object file and we never change it. Convert the data to string using unsafe conversion without allocation. Linking cmd/go (on macOS/amd64), name old alloc/op new alloc/op delta Deadcode_GC 1.25MB ± 0% 1.17MB ± 0% -6.29% (p=0.000 n=20+20) name old allocs/op new allocs/op delta Deadcode_GC 8.98k ± 0% 0.10k ± 3% -98.91% (p=0.000 n=20+20) Change-Id: I33117ad1f991e4f14ce0b38cceec50b041e3c0a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/490915 TryBot-Result: Gopher Robot Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/internal/goobj/objfile.go | 9 +++++++++ src/cmd/link/internal/ld/deadcode.go | 2 +- src/cmd/link/internal/ld/decodesym.go | 10 +++++++--- src/cmd/link/internal/loader/loader.go | 10 ++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index 64d453abdc5..c9d7ca434c4 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -853,6 +853,15 @@ func (r *Reader) Data(i uint32) []byte { return r.BytesAt(base+off, int(end-off)) } +// DataString returns the i-th symbol's data as a string. +func (r *Reader) DataString(i uint32) string { + dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4 + base := r.h.Offsets[BlkData] + off := r.uint32At(dataIdxOff) + end := r.uint32At(dataIdxOff + 4) + return r.StringAt(base+off, end-off) +} + // NRefName returns the number of referenced symbol names. func (r *Reader) NRefName() int { return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index c80bacd92c3..e7028d3b544 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -487,7 +487,7 @@ func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, sym // Decode the method name stored in symbol symIdx. The symbol should contain just the bytes of a method name. func (d *deadcodePass) decodeGenericIfaceMethod(ldr *loader.Loader, symIdx loader.Sym) string { - return string(ldr.Data(symIdx)) + return ldr.DataString(symIdx) } func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig { diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index b0f4b875633..53ed6ccc86a 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -127,9 +127,13 @@ func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs return "" } - data := ldr.Data(r) - nameLen, nameLenLen := binary.Uvarint(data[1:]) - return string(data[1+nameLenLen : 1+nameLenLen+int(nameLen)]) + data := ldr.DataString(r) + n := 1 + binary.MaxVarintLen64 + if len(data) < n { + n = len(data) + } + nameLen, nameLenLen := binary.Uvarint([]byte(data[1:n])) + return data[1+nameLenLen : 1+nameLenLen+int(nameLen)] } func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool { diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 5fcbf160e0f..fa74dcede42 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1247,6 +1247,16 @@ func (l *Loader) Data(i Sym) []byte { return r.Data(li) } +// Returns the symbol content of the i-th symbol as a string. i is global index. +func (l *Loader) DataString(i Sym) string { + if l.IsExternal(i) { + pp := l.getPayload(i) + return string(pp.data) + } + r, li := l.toLocal(i) + return r.DataString(li) +} + // FreeData clears the symbol data of an external symbol, allowing the memory // to be freed earlier. No-op for non-external symbols. // i is global index.