]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: parallelize dwarfcompress
authorJeremy Faller <jeremy@golang.org>
Tue, 25 Feb 2020 02:12:49 +0000 (21:12 -0500)
committerJeremy Faller <jeremy@golang.org>
Tue, 10 Mar 2020 20:28:43 +0000 (20:28 +0000)
Benchmarked on cmd/compile (n=10) on my laptop. Total time is a 15%
improvement:

name                    old time/op    new time/op     delta
Dwarfcompress              181ms ± 7%       62ms ± 7%       -66.01%  (p=0.000 n=10+10)
TotalTime                  865ms ± 5%      742ms ± 4%       -14.19%  (p=0.000 n=10+10)

name                    old alloc/op   new alloc/op    delta
Dwarfcompress             24.5MB ± 0%     24.5MB ± 0%        +0.01%  (p=0.000 n=10+10)

name                    old allocs/op  new allocs/op   delta
Dwarfcompress                344 ± 0%        350 ± 1%        +1.72%  (p=0.000 n=10+10)

name                    old heap-B     new heap-B      delta
Dwarfcompress               164M ± 0%       164M ± 0%          ~     (p=0.232 n=8+7)

Change-Id: Id42033073b021d6a4e1fc75a2f6b7f3605fe5d2f
Reviewed-on: https://go-review.googlesource.com/c/go/+/220843
Run-TryBot: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/dwarf2.go

index 25dda36293a3c2b4e448758115481e6dda7fde18..4b1975dcd9ec5426029ec201a7583b82f51a5278 100644 (file)
@@ -127,6 +127,8 @@ func trampoline(ctxt *Link, s *sym.Symbol) {
 //
 // This is a performance-critical function for the linker; be careful
 // to avoid introducing unnecessary allocations in the main loop.
+// TODO: This function is called in parallel. When the Loader wavefront
+// reaches here, calls into the loader need to be parallel as well.
 func relocsym(target *Target, err *ErrorReporter, lookup LookupFn, syms *ArchSyms, s *sym.Symbol) {
        if len(s.R) == 0 {
                return
@@ -2481,6 +2483,7 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
                if len(s.R) != 0 && wasReadOnly {
                        relocbuf = append(relocbuf[:0], s.P...)
                        s.P = relocbuf
+                       // TODO: This function call needs to be parallelized when the loader wavefront gets here.
                        s.Attr.Set(sym.AttrReadOnly, false)
                }
                relocsym(target, reporter, lookup, archSyms, s)
index 1dce5d7195e6ff0bcf83a46949e92da5f18634e2..172c8a049eb9112e59e848633807f6c43dbbed0b 100644 (file)
@@ -106,37 +106,57 @@ func dwarfaddelfsectionsyms(ctxt *Link) {
 // on the fly. After this, dwarfp will contain a different (new) set of
 // symbols, and sections may have been replaced.
 func dwarfcompress(ctxt *Link) {
+       // compressedSect is a helper type for parallelizing compression.
+       type compressedSect struct {
+               index      int
+               compressed []byte
+               syms       []*sym.Symbol
+       }
+
        supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin
        if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal {
                return
        }
 
-       var start int
-       var newDwarfp []*sym.Symbol
-       Segdwarf.Sections = Segdwarf.Sections[:0]
+       var start, compressedCount int
+       resChannel := make(chan compressedSect)
        for i, s := range dwarfp {
                // Find the boundaries between sections and compress
                // the whole section once we've found the last of its
                // symbols.
                if i+1 >= len(dwarfp) || s.Sect != dwarfp[i+1].Sect {
-                       s1 := compressSyms(ctxt, dwarfp[start:i+1])
-                       if s1 == nil {
-                               // Compression didn't help.
-                               newDwarfp = append(newDwarfp, dwarfp[start:i+1]...)
-                               Segdwarf.Sections = append(Segdwarf.Sections, s.Sect)
-                       } else {
-                               compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):]
-                               sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04)
-                               sect.Length = uint64(len(s1))
-                               newSym := ctxt.Syms.Lookup(compressedSegName, 0)
-                               newSym.P = s1
-                               newSym.Size = int64(len(s1))
-                               newSym.Sect = sect
-                               newDwarfp = append(newDwarfp, newSym)
-                       }
+                       go func(resIndex int, syms []*sym.Symbol) {
+                               resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms}
+                       }(compressedCount, dwarfp[start:i+1])
+                       compressedCount++
                        start = i + 1
                }
        }
+       res := make([]compressedSect, compressedCount)
+       for ; compressedCount > 0; compressedCount-- {
+               r := <-resChannel
+               res[r.index] = r
+       }
+
+       var newDwarfp []*sym.Symbol
+       Segdwarf.Sections = Segdwarf.Sections[:0]
+       for _, z := range res {
+               s := z.syms[0]
+               if z.compressed == nil {
+                       // Compression didn't help.
+                       newDwarfp = append(newDwarfp, z.syms...)
+                       Segdwarf.Sections = append(Segdwarf.Sections, s.Sect)
+               } else {
+                       compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):]
+                       sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04)
+                       sect.Length = uint64(len(z.compressed))
+                       newSym := ctxt.Syms.Lookup(compressedSegName, 0)
+                       newSym.P = z.compressed
+                       newSym.Size = int64(len(z.compressed))
+                       newSym.Sect = sect
+                       newDwarfp = append(newDwarfp, newSym)
+               }
+       }
        dwarfp = newDwarfp
 
        // Re-compute the locations of the compressed DWARF symbols