Commit 8ef45cf6 authored by Cherry Zhang's avatar Cherry Zhang

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: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 1805f425
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
package objabi package objabi
type RelocType int32 type RelocType int16
//go:generate stringer -type=RelocType //go:generate stringer -type=RelocType
const ( const (
......
...@@ -189,13 +189,19 @@ func relocsym(ctxt *Link, s *sym.Symbol) { ...@@ -189,13 +189,19 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name) 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. // TODO(mundaym): remove this special case - see issue 14218.
if ctxt.Arch.Family == sys.S390X { if ctxt.Arch.Family == sys.S390X {
switch r.Type { switch r.Type {
case objabi.R_PCRELDBL: case objabi.R_PCRELDBL:
r.InitExt()
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Variant = sym.RV_390_DBL r.Variant = sym.RV_390_DBL
case objabi.R_CALL: case objabi.R_CALL:
r.InitExt()
r.Variant = sym.RV_390_DBL r.Variant = sym.RV_390_DBL
} }
} }
...@@ -499,9 +505,12 @@ func relocsym(ctxt *Link, s *sym.Symbol) { ...@@ -499,9 +505,12 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
o = r.Add o = r.Add
} }
if ctxt.Arch.Family == sys.PPC64 || ctxt.Arch.Family == sys.S390X {
r.InitExt()
if r.Variant != sym.RV_NONE { if r.Variant != sym.RV_NONE {
o = thearch.Archrelocvariant(ctxt, r, s, o) o = thearch.Archrelocvariant(ctxt, r, s, o)
} }
}
if false { if false {
nam := "<nil>" nam := "<nil>"
......
...@@ -272,6 +272,7 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { ...@@ -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 { func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
r.InitExt()
switch r.Type { switch r.Type {
default: default:
......
...@@ -104,6 +104,7 @@ func gentext(ctxt *ld.Link) { ...@@ -104,6 +104,7 @@ func gentext(ctxt *ld.Link) {
func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym targ := r.Sym
r.InitExt()
switch r.Type { switch r.Type {
default: default:
......
...@@ -25,12 +25,24 @@ type Reloc struct { ...@@ -25,12 +25,24 @@ type Reloc struct {
Off int32 // offset to rewrite Off int32 // offset to rewrite
Siz uint8 // number of bytes to rewrite, 1, 2, or 4 Siz uint8 // number of bytes to rewrite, 1, 2, or 4
Done bool // set to true when relocation is complete Done bool // set to true when relocation is complete
Variant RelocVariant // variation on Type
Type objabi.RelocType // the relocation type Type objabi.RelocType // the relocation type
Add int64 // addend Add int64 // addend
Xadd int64 // addend passed to external linker
Sym *Symbol // symbol the relocation addresses 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 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. // RelocVariant is a linker-internal variation on a relocation.
......
...@@ -211,6 +211,9 @@ func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { ...@@ -211,6 +211,9 @@ func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 {
r.Add = add r.Add = add
r.Type = objabi.R_PCREL r.Type = objabi.R_PCREL
r.Siz = 4 r.Siz = 4
if arch.Family == sys.S390X || arch.Family == sys.PPC64 {
r.InitExt()
}
if arch.Family == sys.S390X { if arch.Family == sys.S390X {
r.Variant = RV_390_DBL r.Variant = RV_390_DBL
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment