cmd/link: reduce the size of Reloc struct

For linking large binaries, the slice of Relocs consumes a large
amount of memory. We can reduce this memory consumption by
shrinking the size of the Reloc struct. This CL moves the fields
used only in external linking or only on PPC64 and S390X to a
lazily initialized side struct.

Linking k8s.io/kubernetes/cmd/kube-apiserver on Linux/AMD64,
before:
inuse_space 1240.25MB total
438.11MB 35.32% 35.32%   438.11MB 35.32%  cmd/link/internal/objfile.(*objReader).readSlices

after:
inuse_space 1123.39MB total
306.85MB 27.31% 55.03%   306.85MB 27.31%  cmd/link/internal/objfile.(*objReader).readSlices

Under GOGC=5 (to simulate system under memory pressure), the max
RSS reduces from ~2.05G to ~1.83G. Even with external linking the
max RSS doesn't increase.

Change-Id: I9bb8a8effaed24a8b3c4b1cfb93e6992b8740f91
Reviewed-on: https://go-review.googlesource.com/c/go/+/173437
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Cherry Zhang 2019-04-23 11:34:58 -04:00
parent 1805f425ad
commit 8ef45cf60b
6 changed files with 38 additions and 12 deletions

View File

@ -30,7 +30,7 @@
package objabi
type RelocType int32
type RelocType int16
//go:generate stringer -type=RelocType
const (

View File

@ -189,13 +189,19 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
}
if ctxt.LinkMode == LinkExternal {
r.InitExt()
}
// TODO(mundaym): remove this special case - see issue 14218.
if ctxt.Arch.Family == sys.S390X {
switch r.Type {
case objabi.R_PCRELDBL:
r.InitExt()
r.Type = objabi.R_PCREL
r.Variant = sym.RV_390_DBL
case objabi.R_CALL:
r.InitExt()
r.Variant = sym.RV_390_DBL
}
}
@ -499,8 +505,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
o = r.Add
}
if r.Variant != sym.RV_NONE {
o = thearch.Archrelocvariant(ctxt, r, s, o)
if ctxt.Arch.Family == sys.PPC64 || ctxt.Arch.Family == sys.S390X {
r.InitExt()
if r.Variant != sym.RV_NONE {
o = thearch.Archrelocvariant(ctxt, r, s, o)
}
}
if false {

View File

@ -272,6 +272,7 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
}
func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
r.InitExt()
switch r.Type {
default:

View File

@ -104,6 +104,7 @@ func gentext(ctxt *ld.Link) {
func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
r.InitExt()
switch r.Type {
default:

View File

@ -22,15 +22,27 @@ import (
//
// Some relocations are created by cmd/link.
type Reloc struct {
Off int32 // offset to rewrite
Siz uint8 // number of bytes to rewrite, 1, 2, or 4
Done bool // set to true when relocation is complete
Variant RelocVariant // variation on Type
Type objabi.RelocType // the relocation type
Add int64 // addend
Xadd int64 // addend passed to external linker
Sym *Symbol // symbol the relocation addresses
Xsym *Symbol // symbol passed to external linker
Off int32 // offset to rewrite
Siz uint8 // number of bytes to rewrite, 1, 2, or 4
Done bool // set to true when relocation is complete
Type objabi.RelocType // the relocation type
Add int64 // addend
Sym *Symbol // symbol the relocation addresses
*relocExt // extra fields (see below), may be nil, call InitExt before use
}
// relocExt contains extra fields in Reloc that are used only in
// certain cases.
type relocExt struct {
Xadd int64 // addend passed to external linker
Xsym *Symbol // symbol passed to external linker
Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X
}
func (r *Reloc) InitExt() {
if r.relocExt == nil {
r.relocExt = new(relocExt)
}
}
// RelocVariant is a linker-internal variation on a relocation.

View File

@ -211,6 +211,9 @@ func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
r.Add = add
r.Type = objabi.R_PCREL
r.Siz = 4
if arch.Family == sys.S390X || arch.Family == sys.PPC64 {
r.InitExt()
}
if arch.Family == sys.S390X {
r.Variant = RV_390_DBL
}