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:
parent
b0b185c5fa
commit
a3873ab49f
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user