mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 17:56:45 +08:00
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.
This commit is contained in:
20
proc/proc.go
20
proc/proc.go
@ -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
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user