From f92c64045f5effd4339749b8ce3b63b88cfef4d4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 21 Sep 2020 12:19:47 +0200 Subject: 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 TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- src/debug/dwarf/entry_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/debug/dwarf/entry_test.go') diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go index 4c9aad21f3..2e6ee048aa 100644 --- a/src/debug/dwarf/entry_test.go +++ b/src/debug/dwarf/entry_test.go @@ -7,6 +7,7 @@ package dwarf_test import ( . "debug/dwarf" "encoding/binary" + "path/filepath" "reflect" "testing" ) @@ -209,3 +210,44 @@ func Test64Bit(t *testing.T) { } } } + +func TestUnitIteration(t *testing.T) { + // Iterate over all ELF test files we have and ensure that + // we get the same set of compilation units skipping (method 0) + // and not skipping (method 1) CU children. + files, err := filepath.Glob(filepath.Join("testdata", "*.elf")) + if err != nil { + t.Fatal(err) + } + for _, file := range files { + t.Run(file, func(t *testing.T) { + d := elfData(t, file) + var units [2][]interface{} + for method := range units { + for r := d.Reader(); ; { + ent, err := r.Next() + if err != nil { + t.Fatal(err) + } + if ent == nil { + break + } + if ent.Tag == TagCompileUnit { + units[method] = append(units[method], ent.Val(AttrName)) + } + if method == 0 { + if ent.Tag != TagCompileUnit { + t.Fatalf("found unexpected tag %v on top level", ent.Tag) + } + r.SkipChildren() + } + } + } + t.Logf("skipping CUs: %v", units[0]) + t.Logf("not-skipping CUs: %v", units[1]) + if !reflect.DeepEqual(units[0], units[1]) { + t.Fatal("set of CUs differ") + } + }) + } +} -- cgit v1.3