提交 c66c6408 编写于 作者: A aarzilli

proc: Caching type offsets

Caches the mapping of type names to offset in debug_info to speed up
variable evaluation.

BEFORE:
	BenchmarkArray-4         	     100	  13'238'441 ns/op	   0.62 MB/s
	BenchmarkArrayPointer-4  	     200	  10'044'093 ns/op	   0.87 MB/s
	BenchmarkMap-4           	    1000	   1'332'530 ns/op	   0.77 MB/s
	BenchmarkGoroutinesInfo-4	      10	 114'677'462 ns/op
	BenchmarkLocalVariables-4	    2000	   1'223'975 ns/op
AFTER:
	BenchmarkArray-4         	     200	   9'925'686 ns/op	   0.83 MB/s
	BenchmarkArrayPointer-4  	     100	  11'143'930 ns/op	   0.78 MB/s
	BenchmarkMap-4           	    2000	   1'302'520 ns/op	   0.79 MB/s
	BenchmarkGoroutinesInfo-4	      30	  35'079'549 ns/op
	BenchmarkLocalVariables-4	    1000	   1'137'299 ns/op

Note in particular the speedup of BenchmarkGoroutinesInfo, since
proc.(*Variable).parseG is a function we call a lot.
上级 758f76ff
......@@ -58,6 +58,7 @@ type Process struct {
exited bool
ptraceChan chan func()
ptraceDoneChan chan interface{}
types map[string]dwarf.Offset
}
// New returns an initialized Process struct. Before returning,
......@@ -149,11 +150,12 @@ func (dbp *Process) LoadInformation(path string) error {
return err
}
wg.Add(4)
wg.Add(5)
go dbp.loadProcessInformation(&wg)
go dbp.parseDebugFrame(exe, &wg)
go dbp.obtainGoSymbols(exe, &wg)
go dbp.parseDebugLineInfo(exe, &wg)
go dbp.loadTypeMap(&wg)
wg.Wait()
return nil
......@@ -658,19 +660,9 @@ func (dbp *Process) Funcs() []gosym.Func {
// Types returns list of types present in the debugged program.
func (dbp *Process) Types() ([]string, error) {
reader := dbp.DwarfReader()
types := []string{}
seen := map[string]struct{}{}
for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() {
if err != nil {
return nil, err
}
if n, ok := entry.Val(dwarf.AttrName).(string); ok {
if _, isseen := seen[n]; !isseen {
seen[n] = struct{}{}
types = append(types, n)
}
}
types := make([]string, 0, len(dbp.types))
for k := range dbp.types {
types = append(types, k)
}
return types, nil
}
......
......@@ -1626,7 +1626,7 @@ func TestPackageVariables(t *testing.T) {
func TestIssue149(t *testing.T) {
ver, _ := ParseVersionString(runtime.Version())
if ver.Major > 0 && !ver.AfterOrEqual(GoVersion{1, 7, 0, 0, 0}) {
if ver.Major > 0 && !ver.AfterOrEqual(GoVersion{1, 7, 0, 0, 0}) {
return
}
// setting breakpoint on break statement
......
package proc
import (
"github.com/derekparker/delve/dwarf/reader"
"go/ast"
"golang.org/x/debug/dwarf"
"reflect"
"strings"
"sync"
)
// Do not call this function directly it isn't able to deal correctly with package paths
func (dbp *Process) findType(name string) (dwarf.Type, error) {
reader := dbp.DwarfReader()
typentry, err := reader.SeekToTypeNamed(name)
if err != nil {
return nil, err
off, found := dbp.types[name]
if !found {
return nil, reader.TypeNotFoundErr
}
return dbp.dwarf.Type(typentry.Offset)
return dbp.dwarf.Type(off)
}
func (dbp *Process) pointerTo(typ dwarf.Type) dwarf.Type {
......@@ -83,6 +84,24 @@ func (dbp *Process) loadPackageMap() error {
return nil
}
func (dbp *Process) loadTypeMap(wg *sync.WaitGroup) {
defer wg.Done()
dbp.types = make(map[string]dwarf.Offset)
reader := dbp.DwarfReader()
for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() {
if err != nil {
break
}
name, ok := entry.Val(dwarf.AttrName).(string)
if !ok {
continue
}
if _, exists := dbp.types[name]; !exists {
dbp.types[name] = entry.Offset
}
}
}
func (dbp *Process) expandPackagesInType(expr ast.Expr) {
switch e := expr.(type) {
case *ast.ArrayType:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册