cmd/internal/obj: reduce allocations in object file writing

Some object file writer functions are structured like, having a
local variable, setting fields, then passing it to a Write method
which eventually calls io.Writer.Write. As the Write call is an
interface call it escapes the parameter, which in turn causes the
local variable to be heap allocated. To reduce allocation, use
pre-allocated scratch space instead.

Reduce number of allocations in the compiler:
name        old allocs/op     new allocs/op     delta
Template           679k ± 0%         644k ± 0%  -5.17%  (p=0.000 n=20+20)
Unicode            603k ± 0%         581k ± 0%  -3.67%  (p=0.000 n=20+20)
GoTypes           3.83M ± 0%        3.63M ± 0%  -5.30%  (p=0.000 n=20+20)
Compiler           353k ± 0%         342k ± 0%  -3.09%  (p=0.000 n=18+19)
SSA               31.4M ± 0%        30.4M ± 0%  -3.02%  (p=0.000 n=20+20)
Flate              397k ± 0%         373k ± 0%  -5.92%  (p=0.000 n=20+18)
GoParser           777k ± 0%         735k ± 0%  -5.37%  (p=0.000 n=20+20)
Reflect           2.07M ± 0%        1.90M ± 0%  -7.89%  (p=0.000 n=18+20)
Tar                605k ± 0%         568k ± 0%  -6.26%  (p=0.000 n=19+16)
XML                801k ± 0%         766k ± 0%  -4.36%  (p=0.000 n=20+20)
[Geo mean]        1.18M             1.12M       -5.02%

Change-Id: I9d02a72e459e645527196ac54b6ee643a5ea6bd3
Reviewed-on: https://go-review.googlesource.com/c/go/+/449637
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Cherry Mui 2022-11-10 16:10:32 -05:00
parent 79950a4162
commit 5497300d9c
2 changed files with 27 additions and 18 deletions

View file

@ -220,6 +220,16 @@ type writer struct {
ctxt *Link
pkgpath string // the package import path (escaped), "" if unknown
pkglist []string // list of packages referenced, indexed by ctxt.pkgIdx
// scratch space for writing (the Write methods escape
// as they are interface calls)
tmpSym goobj.Sym
tmpReloc goobj.Reloc
tmpAux goobj.Aux
tmpHash64 goobj.Hash64Type
tmpHash goobj.HashType
tmpRefFlags goobj.RefFlags
tmpRefName goobj.RefName
}
// prepare package index list
@ -379,7 +389,7 @@ func (w *writer) Sym(s *LSym) {
if s.Size > cutoff {
w.ctxt.Diag("%s: symbol too large (%d bytes > %d bytes)", s.Name, s.Size, cutoff)
}
var o goobj.Sym
o := &w.tmpSym
o.SetName(name, w.Writer)
o.SetABI(abi)
o.SetType(uint8(s.Type))
@ -394,16 +404,16 @@ func (w *writer) Hash64(s *LSym) {
if !s.ContentAddressable() || len(s.R) != 0 {
panic("Hash of non-content-addressable symbol")
}
b := contentHash64(s)
w.Bytes(b[:])
w.tmpHash64 = contentHash64(s)
w.Bytes(w.tmpHash64[:])
}
func (w *writer) Hash(s *LSym) {
if !s.ContentAddressable() {
panic("Hash of non-content-addressable symbol")
}
b := w.contentHash(s)
w.Bytes(b[:])
w.tmpHash = w.contentHash(s)
w.Bytes(w.tmpHash[:])
}
// contentHashSection returns a mnemonic for s's section.
@ -538,7 +548,7 @@ func makeSymRef(s *LSym) goobj.SymRef {
}
func (w *writer) Reloc(r *Reloc) {
var o goobj.Reloc
o := &w.tmpReloc
o.SetOff(r.Off)
o.SetSiz(r.Siz)
o.SetType(uint16(r.Type))
@ -548,7 +558,7 @@ func (w *writer) Reloc(r *Reloc) {
}
func (w *writer) aux1(typ uint8, rs *LSym) {
var o goobj.Aux
o := &w.tmpAux
o.SetType(typ)
o.SetSym(makeSymRef(rs))
o.Write(w.Writer)
@ -618,7 +628,7 @@ func (w *writer) refFlags() {
if flag2 == 0 {
return // no need to write zero flags
}
var o goobj.RefFlags
o := &w.tmpRefFlags
o.SetSym(symref)
o.SetFlag2(flag2)
o.Write(w.Writer)
@ -644,7 +654,7 @@ func (w *writer) refNames() {
}
seen[rs] = true
symref := makeSymRef(rs)
var o goobj.RefName
o := &w.tmpRefName
o.SetSym(symref)
o.SetName(rs.Name, w.Writer)
o.Write(w.Writer)