From 2e2ef666b4d0bf0e86aaa3afbef7fc17f34232e6 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 24 Oct 2019 11:59:49 -0400 Subject: [PATCH] [dev.link] cmd/link/internal/loader: add PkgNone resolver cache MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add a cache for the loader.Loader.resolve() method to use when looking mapping local PkgNone symbols to global symbol indices. This helps avoid repeated map lookups during deadcode and other early phases of the linker when we haven't fully read in all of object file symbols. Benchstat numbers: name old time/op new time/op delta LinkCompiler 1.97s ±13% 1.67s ± 8% -15.34% (p=0.000 n=20+20) LinkWithoutDebugCompiler 1.48s ±12% 1.21s ±11% -18.14% (p=0.000 n=20+20) name old user-time/op new user-time/op delta LinkCompiler 2.19s ± 9% 2.04s ±17% -6.98% (p=0.002 n=19+20) LinkWithoutDebugCompiler 1.29s ±13% 1.20s ±13% -7.70% (p=0.000 n=20+20) Change-Id: I4b0b05c8208ee44ee9405b24774b84443e486831 Reviewed-on: https://go-review.googlesource.com/c/go/+/203197 Run-TryBot: Than McIntosh TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/link/internal/loader/loader.go | 32 ++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 846e954aa1..52809c63da 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -59,6 +59,7 @@ type oReader struct { version int // version of static symbol flags uint32 // read from object file pkgprefix string + rcache []Sym // cache mapping local PkgNone symbol to resolved Sym } type objIdx struct { @@ -257,6 +258,26 @@ func (l *Loader) toLocal(i Sym) (*oReader, int) { return l.objs[k-1].r, int(i - l.objs[k-1].i) } +// rcacheGet checks for a valid entry for 's' in the readers cache, +// where 's' is a local PkgIdxNone ref or def, or zero if +// the cache is empty or doesn't contain a value for 's'. +func (or *oReader) rcacheGet(symIdx uint32) Sym { + if len(or.rcache) > 0 { + return or.rcache[symIdx] + } + return 0 +} + +// rcacheSet installs a new entry in the oReader's PkgNone +// resolver cache for the specified PkgIdxNone ref or def, +// allocating a new cache if needed. +func (or *oReader) rcacheSet(symIdx uint32, gsym Sym) { + if len(or.rcache) == 0 { + or.rcache = make([]Sym, or.NNonpkgdef()+or.NNonpkgref()) + } + or.rcache[symIdx] = gsym +} + // Resolve a local symbol reference. Return global index. func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym { var rr *oReader @@ -267,13 +288,20 @@ func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym { } return 0 case goobj2.PkgIdxNone: + // Check for cached version first + if cached := r.rcacheGet(s.SymIdx); cached != 0 { + return cached + } // Resolve by name i := int(s.SymIdx) + r.NSym() osym := goobj2.Sym{} osym.Read(r.Reader, r.SymOff(i)) name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) v := abiToVer(osym.ABI, r.version) - return l.Lookup(name, v) + gsym := l.Lookup(name, v) + // Add to cache, then return. + r.rcacheSet(s.SymIdx, gsym) + return gsym case goobj2.PkgIdxBuiltin: return l.builtinSyms[s.SymIdx] case goobj2.PkgIdxSelf: @@ -549,7 +577,7 @@ func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib * } localSymVersion := syms.IncVersion() pkgprefix := objabi.PathToPrefix(lib.Pkg) + "." - or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix} + or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, nil} // Autolib lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...) -- 2.48.1