From 8ef45cf60b347abb1a08416fca1b6d19d317b26e Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Tue, 23 Apr 2019 11:34:58 -0400 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/cmd/internal/objabi/reloctype.go | 2 +- src/cmd/link/internal/ld/data.go | 13 ++++++++++-- src/cmd/link/internal/ppc64/asm.go | 1 + src/cmd/link/internal/s390x/asm.go | 1 + src/cmd/link/internal/sym/reloc.go | 30 +++++++++++++++++++--------- src/cmd/link/internal/sym/symbol.go | 3 +++ 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index f619e017d8..94d5469d9c 100644 --- a/src/cmd/internal/objabi/reloctype.go +++ b/src/cmd/internal/objabi/reloctype.go @@ -30,7 +30,7 @@ package objabi -type RelocType int32 +type RelocType int16 //go:generate stringer -type=RelocType const ( diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 3b551db853..8e35f5c9dc 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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 { diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 365a45ec13..c315b4bfc2 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -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: diff --git a/src/cmd/link/internal/s390x/asm.go b/src/cmd/link/internal/s390x/asm.go index 8540377400..040c573705 100644 --- a/src/cmd/link/internal/s390x/asm.go +++ b/src/cmd/link/internal/s390x/asm.go @@ -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: diff --git a/src/cmd/link/internal/sym/reloc.go b/src/cmd/link/internal/sym/reloc.go index 9c862f109d..4809db8c80 100644 --- a/src/cmd/link/internal/sym/reloc.go +++ b/src/cmd/link/internal/sym/reloc.go @@ -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. diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go index 88a28f5b99..d115a3326f 100644 --- a/src/cmd/link/internal/sym/symbol.go +++ b/src/cmd/link/internal/sym/symbol.go @@ -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 } -- 2.48.1