1
0
mirror of https://github.com/golang/go synced 2024-11-18 15:14:44 -07:00

[dev.link] cmd/link: parallelize dwarfcompress

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>
This commit is contained in:
Jeremy Faller 2020-02-24 21:12:49 -05:00
parent b0b185c5fa
commit a3873ab49f
2 changed files with 41 additions and 18 deletions

View 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)

View 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