From 404f626ee5c41cefef976a9185a40af4359e7152 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 29 Apr 2020 18:46:44 -0400 Subject: [PATCH] [dev.link] cmd/link: minor performance tweaks in dodata Tweak doDataSect to reduce symbol sorting overhead, and calculate size ahead of allocating the ctxt.datap slice. Yields a small speedup (2-3%) linking kubelet. Change-Id: I82869f5276caa4bee9f6e6f41da2b240e601ce50 Reviewed-on: https://go-review.googlesource.com/c/go/+/231047 Run-TryBot: Than McIntosh Reviewed-by: Jeremy Faller Reviewed-by: Cherry Zhang --- src/cmd/link/internal/ld/data.go | 35 +++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 84b5b494b2..5520d22cf2 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1879,6 +1879,11 @@ func (state *dodataState) allocateDataSections2(ctxt *Link) { Errorf(nil, "read-only data segment too large: %d", state.datsize) } + siz := 0 + for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ { + siz += len(state.data2[symn]) + } + ctxt.datap2 = make([]loader.Sym, 0, siz) for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ { ctxt.datap2 = append(ctxt.datap2, state.data2[symn]...) } @@ -1919,11 +1924,19 @@ func (state *dodataState) allocateDwarfSections2(ctxt *Link) { } } +type symNameSize struct { + name string + sz int64 + sym loader.Sym +} + func (state *dodataState) dodataSect2(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) { var head, tail loader.Sym ldr := ctxt.loader - for _, s := range syms { + sl := make([]symNameSize, len(syms)) + for k, s := range syms { ss := ldr.SymSize(s) + sl[k] = symNameSize{name: ldr.SymName(s), sz: ss, sym: s} ds := int64(len(ldr.Data(s))) switch { case ss < ds: @@ -1956,8 +1969,8 @@ func (state *dodataState) dodataSect2(ctxt *Link, symn sym.SymKind, syms []loade checkSize := symn != sym.SELFGOT // Perform the sort. - sort.Slice(syms, func(i, j int) bool { - si, sj := syms[i], syms[j] + sort.Slice(sl, func(i, j int) bool { + si, sj := sl[i].sym, sl[j].sym switch { case si == head, sj == tail: return true @@ -1965,29 +1978,31 @@ func (state *dodataState) dodataSect2(ctxt *Link, symn sym.SymKind, syms []loade return false } if checkSize { - isz := ldr.SymSize(si) - jsz := ldr.SymSize(sj) + isz := sl[i].sz + jsz := sl[j].sz if isz != jsz { return isz < jsz } } - iname := ldr.SymName(si) - jname := ldr.SymName(sj) + iname := sl[i].name + jname := sl[j].name if iname != jname { return iname < jname } return si < sj }) - // Reap alignment. - for k := range syms { - s := syms[k] + // Reap alignment, construct result + syms = syms[:0] + for k := range sl { + s := sl[k].sym if s != head && s != tail { align := state.symalign2(s) if maxAlign < align { maxAlign = align } } + syms = append(syms, s) } return syms, maxAlign