aboutsummaryrefslogtreecommitdiff
path: root/src/debug/dwarf/entry.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-09-21 12:19:47 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-09-21 20:14:27 +0000
commitf92c64045f5effd4339749b8ce3b63b88cfef4d4 (patch)
tree6b3de5367b1696152e6e3e5ad02fda17cdf215ef /src/debug/dwarf/entry.go
parent7e9369a517d9ebf867748719948d8cbccec3bc57 (diff)
downloadgo-f92c64045f5effd4339749b8ce3b63b88cfef4d4.tar.xz
debug/dwarf: speed up SkipChildren for compilation units
For a common pattern of iterating only over top-level compilation units (CU) Reader.SkipChildren has decode and meterialize all CU subentries just to skip them, because DW_TAG_compile_unit does not have DW_AT_sibling. However, CUs have total size encoded before the unit and we already parse them and know all unit sizes. Optimize Reader.SkipChildren to use that size when skipping CUs children. This speeds up iteration over a 1.3GB object file from 7.5s to 0.73s. Change-Id: I2a8f00955159b4bd13571409f4817805f934cb69 Reviewed-on: https://go-review.googlesource.com/c/go/+/256217 Run-TryBot: Dmitry Vyukov <dvyukov@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Trust: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/debug/dwarf/entry.go')
-rw-r--r--src/debug/dwarf/entry.go21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/debug/dwarf/entry.go b/src/debug/dwarf/entry.go
index 01f2190db7..88eb56936b 100644
--- a/src/debug/dwarf/entry.go
+++ b/src/debug/dwarf/entry.go
@@ -717,6 +717,7 @@ type Reader struct {
d *Data
err error
unit int
+ lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit
lastChildren bool // .Children of last entry returned by Next
lastSibling Offset // .Val(AttrSibling) of last entry returned by Next
cu *Entry // current compilation unit
@@ -774,13 +775,18 @@ func (r *Reader) Seek(off Offset) {
// maybeNextUnit advances to the next unit if this one is finished.
func (r *Reader) maybeNextUnit() {
for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
- r.unit++
- u := &r.d.unit[r.unit]
- r.b = makeBuf(r.d, u, "info", u.off, u.data)
- r.cu = nil
+ r.nextUnit()
}
}
+// nextUnit advances to the next unit.
+func (r *Reader) nextUnit() {
+ r.unit++
+ u := &r.d.unit[r.unit]
+ r.b = makeBuf(r.d, u, "info", u.off, u.data)
+ r.cu = nil
+}
+
// Next reads the next entry from the encoded entry stream.
// It returns nil, nil when it reaches the end of the section.
// It returns an error if the current offset is invalid or the data at the
@@ -799,12 +805,14 @@ func (r *Reader) Next() (*Entry, error) {
r.err = r.b.err
return nil, r.err
}
+ r.lastUnit = false
if e != nil {
r.lastChildren = e.Children
if r.lastChildren {
r.lastSibling, _ = e.Val(AttrSibling).(Offset)
}
if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
+ r.lastUnit = true
r.cu = e
}
} else {
@@ -830,6 +838,11 @@ func (r *Reader) SkipChildren() {
return
}
+ if r.lastUnit && r.unit+1 < len(r.d.unit) {
+ r.nextUnit()
+ return
+ }
+
for {
e, err := r.Next()
if err != nil || e == nil || e.Tag == 0 {