1
0
mirror of https://github.com/golang/go synced 2024-11-24 06:30:22 -07:00

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 <mdempsky@google.com>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Shahar Kohanim 2016-03-09 23:28:05 +02:00 committed by David Crawshaw
parent bb48b864b1
commit eb57a1dd75
2 changed files with 41 additions and 19 deletions

View File

@ -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

View File

@ -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
}