]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: use string map for symbols with single version
authorShahar Kohanim <skohanim@gmail.com>
Wed, 9 Mar 2016 21:28:05 +0000 (23:28 +0200)
committerDavid Crawshaw <crawshaw@golang.org>
Sat, 12 Mar 2016 11:11:10 +0000 (11:11 +0000)
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>

src/cmd/link/internal/ld/link.go
src/cmd/link/internal/ld/sym.go

index 0fadaf4b85be539efdd55a837baf5a88ba9a1d0c..2f2be3a5cb703660f30fdacf20cc465745059926 100644 (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
index 6df4839468d63c6478012927313a142a043db4d6..05b3252add268eacc6119fe4ed02285a323224c1 100644 (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
 }