]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/ld: avoid Reloc copies in range loops
authorisharipo <iskander.sharipov@intel.com>
Thu, 17 May 2018 16:47:52 +0000 (19:47 +0300)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 21 Aug 2018 02:29:51 +0000 (02:29 +0000)
Copying sym.Reloc in loops hurts performance as
it has 48 byte size (on 64-bit platforms).

There are quite many symbols and each of them has more than 1
relocation (so, it's possible to have more than 1kk relocs).
The're also traversed more than once in some code paths.

By using pointers to them, copies are avoided.

For linking "hello world" example from net/http:

name      old time/op  new time/op  delta
Linker-4   530ms ± 2%   521ms ± 3%  -1.80%  (p=0.000 n=17+20)

Change-Id: I6518aec69d6adcd137f84b5c089ceab4cb4ea2dd
Reviewed-on: https://go-review.googlesource.com/113636
Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/link/internal/ld/ar.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/lib.go

index ae7554c929609ba502dd53e5346894c2ecab2c4a..779f3565f9d3aca056540885ae2c3ec4a49f6a27 100644 (file)
@@ -105,7 +105,8 @@ func hostArchive(ctxt *Link, name string) {
        for any {
                var load []uint64
                for _, s := range ctxt.Syms.Allsym {
-                       for _, r := range s.R {
+                       for i := range s.R {
+                               r := &s.R[i] // Copying sym.Reloc has measurable impact on peformance
                                if r.Sym != nil && r.Sym.Type == sym.SXREF {
                                        if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
                                                load = append(load, off)
index d71b8b6ac7b615b1b1c1075b1e45e816078fca9a..5dd4aac03e37641dab122392f12733e0ef275d00 100644 (file)
@@ -772,7 +772,8 @@ func Datblk(ctxt *Link, addr int64, size int64) {
                if ctxt.LinkMode != LinkExternal {
                        continue
                }
-               for _, r := range sym.R {
+               for i := range sym.R {
+                       r := &sym.R[i] // Copying sym.Reloc has measurable impact on peformance
                        rsname := ""
                        if r.Sym != nil {
                                rsname = r.Sym.Name
index 540f4068cb8ea8be8a2816a0f0631f4ce49c745b..df989cc94486a77cabfc77d73331cb22dd648fc7 100644 (file)
@@ -245,8 +245,8 @@ func (d *deadcodepass) init() {
                                // but we do keep the symbols it refers to.
                                exports := d.ctxt.Syms.ROLookup("go.plugin.exports", 0)
                                if exports != nil {
-                                       for _, r := range exports.R {
-                                               d.mark(r.Sym, nil)
+                                       for i := range exports.R {
+                                               d.mark(exports.R[i].Sym, nil)
                                        }
                                }
                        }
index ae6f90b079c5c00d1774ce14ed49c669c0be08e2..c803180cadd08b85f8aed468b2194e3b183fd824 100644 (file)
@@ -1061,7 +1061,8 @@ func getCompilationDir() string {
 func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
        dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
        dsym.Type = sym.SDWARFINFO
-       for _, r := range dsym.R {
+       for i := range dsym.R {
+               r := &dsym.R[i] // Copying sym.Reloc has measurable impact on peformance
                if r.Type == objabi.R_DWARFSECREF && r.Sym.Size == 0 {
                        if ctxt.BuildMode == BuildModeShared {
                                // These type symbols may not be present in BuildModeShared. Skip.
@@ -1090,7 +1091,8 @@ func collectAbstractFunctions(ctxt *Link, fn *sym.Symbol, dsym *sym.Symbol, absf
 
        // Walk the relocations on the primary subprogram DIE and look for
        // references to abstract funcs.
-       for _, reloc := range dsym.R {
+       for i := range dsym.R {
+               reloc := &dsym.R[i] // Copying sym.Reloc has measurable impact on peformance
                candsym := reloc.Sym
                if reloc.Type != objabi.R_DWARFSECREF {
                        continue
@@ -1801,7 +1803,8 @@ func collectlocs(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit) []*sy
        empty := true
        for _, u := range units {
                for _, fn := range u.funcDIEs {
-                       for _, reloc := range fn.R {
+                       for i := range fn.R {
+                               reloc := &fn.R[i] // Copying sym.Reloc has measurable impact on peformance
                                if reloc.Type == objabi.R_DWARFSECREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
                                        reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
                                        syms = append(syms, reloc.Sym)
index 9f8945775370d5577c32b33c28e33634f9bae498..d86b2aa5446ac4493291b33233d4264177d237bd 100644 (file)
@@ -503,7 +503,8 @@ func (ctxt *Link) loadlib() {
                // objects, try to read them from the libgcc file.
                any := false
                for _, s := range ctxt.Syms.Allsym {
-                       for _, r := range s.R {
+                       for i := range s.R {
+                               r := &s.R[i] // Copying sym.Reloc has measurable impact on peformance
                                if r.Sym != nil && r.Sym.Type == sym.SXREF && r.Sym.Name != ".got" {
                                        any = true
                                        break