From: Shahar Kohanim Date: Wed, 9 Mar 2016 21:28:05 +0000 (+0200) Subject: cmd/link: use string map for symbols with single version X-Git-Tag: go1.7beta1~1371 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=eb57a1dd7525595b853963612b277150fa6c50c2;p=gostls13.git cmd/link: use string map for symbols with single version Reduces link time by ~3% Results with gc on: name old s/op new s/op delta LinkCmdGo 0.82 ± 2% 0.78 ± 2% -3.90% (p=0.000 n=17+17) LinkJuju 7.11 ± 7% 6.87 ± 6% -3.41% (p=0.012 n=20+19) Less noisy results with gc turned off: name old s/op new s/op delta LinkCmdGo 0.66 ± 2% 0.64 ± 2% -3.14% (p=0.000 n=18+20) LinkJuju 5.91 ± 1% 5.72 ± 2% -3.17% (p=0.000 n=20+20) Change-Id: I4cac7933b0b22d0aee18255e1ab54550ad364593 Reviewed-on: https://go-review.googlesource.com/20478 Reviewed-by: Matthew Dempsky Reviewed-by: David Crawshaw Run-TryBot: David Crawshaw --- diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index 0fadaf4b85..2f2be3a5cb 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -161,17 +161,23 @@ type Shlib struct { } type Link struct { - Thechar int32 - Thestring string - Goarm int32 - Headtype int - Arch *LinkArch - Debugasm int32 - Debugvlog int32 - Bso *obj.Biobuf - Windows int32 - Goroot string - Hash map[symVer]*LSym + Thechar int32 + Thestring string + Goarm int32 + Headtype int + Arch *LinkArch + Debugasm int32 + Debugvlog int32 + Bso *obj.Biobuf + Windows int32 + Goroot string + + // Map for fast access of symbols based on name. + HashName map[string]*LSym + // Fallback map based also on version, for symbols + // with more than one version (see func _lookup). + HashVersion map[symVer]*LSym + Allsym []*LSym Nsymbol int32 Tlsg *LSym diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go index 6df4839468..05b3252add 100644 --- a/src/cmd/link/internal/ld/sym.go +++ b/src/cmd/link/internal/ld/sym.go @@ -58,11 +58,12 @@ var headers = []struct { func linknew(arch *LinkArch) *Link { ctxt := &Link{ - Hash: make(map[symVer]*LSym, 100000), // preallocate about 2mb for hash - Allsym: make([]*LSym, 0, 100000), - Arch: arch, - Version: obj.HistVersion, - Goroot: obj.Getgoroot(), + HashName: make(map[string]*LSym, 100000), // preallocate about 2mb for hash + HashVersion: make(map[symVer]*LSym), + Allsym: make([]*LSym, 0, 100000), + Arch: arch, + Version: obj.HistVersion, + Goroot: obj.Getgoroot(), } p := obj.Getgoarch() @@ -182,9 +183,20 @@ type symVer struct { } func _lookup(ctxt *Link, symb string, v int, creat int) *LSym { - s := ctxt.Hash[symVer{symb, v}] + // Most symbols have only a single version, and a string key + // is faster to search for. So we store the first symbol in HashName, + // keyed only by symbol name. If there are name collisions, the + // alternate versions are stored in the spill over map + // HashVersion. + s, exist := ctxt.HashName[symb] if s != nil { - return s + if int(s.Version) == v { + return s + } + s = ctxt.HashVersion[symVer{symb, v}] + if s != nil { + return s + } } if creat == 0 { return nil @@ -192,7 +204,11 @@ func _lookup(ctxt *Link, symb string, v int, creat int) *LSym { s = linknewsym(ctxt, symb, v) s.Extname = s.Name - ctxt.Hash[symVer{symb, v}] = s + if exist { + ctxt.HashVersion[symVer{symb, v}] = s + } else { + ctxt.HashName[symb] = s + } return s }