1
0
mirror of https://github.com/golang/go synced 2024-11-23 00:40:08 -07:00

cmd/link: remove allocation in decoding type name

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 <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Mui 2023-05-01 12:54:27 -04:00
parent fa4781a415
commit 630ef2edc2
4 changed files with 27 additions and 4 deletions

View File

@ -853,6 +853,15 @@ func (r *Reader) Data(i uint32) []byte {
return r.BytesAt(base+off, int(end-off)) 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. // NRefName returns the number of referenced symbol names.
func (r *Reader) NRefName() int { func (r *Reader) NRefName() int {
return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize

View File

@ -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. // 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 { 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 { func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {

View File

@ -127,9 +127,13 @@ func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs
return "" return ""
} }
data := ldr.Data(r) data := ldr.DataString(r)
nameLen, nameLenLen := binary.Uvarint(data[1:]) n := 1 + binary.MaxVarintLen64
return string(data[1+nameLenLen : 1+nameLenLen+int(nameLen)]) 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 { func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool {

View File

@ -1247,6 +1247,16 @@ func (l *Loader) Data(i Sym) []byte {
return r.Data(li) 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 // FreeData clears the symbol data of an external symbol, allowing the memory
// to be freed earlier. No-op for non-external symbols. // to be freed earlier. No-op for non-external symbols.
// i is global index. // i is global index.