proc/eval: optimize variable lookup (#925)
Variable lookup is slow because it requires a full scan of debug_info to check for package variables, this doesn't matter much in interactive use but can slow down evaluation of breakpoint conditions significantly. Providing benchmark proof for this is hard since this effect doesn't show for small programs with small debug_info sections.
This commit is contained in:
parent
07e53f7cbb
commit
222cf7fc55
@ -34,6 +34,7 @@ type BinaryInfo struct {
|
||||
lineInfo line.DebugLines
|
||||
goSymTable *gosym.Table
|
||||
types map[string]dwarf.Offset
|
||||
packageVars map[string]dwarf.Offset
|
||||
functions []functionDebugInfo
|
||||
gStructOffset uint64
|
||||
|
||||
|
||||
@ -132,6 +132,7 @@ func (v sortFunctionsDebugInfoByLowpc) Swap(i, j int) {
|
||||
func (bi *BinaryInfo) loadDebugInfoMaps(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
bi.types = make(map[string]dwarf.Offset)
|
||||
bi.packageVars = make(map[string]dwarf.Offset)
|
||||
bi.functions = []functionDebugInfo{}
|
||||
reader := bi.DwarfReader()
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
@ -140,23 +141,23 @@ func (bi *BinaryInfo) loadDebugInfoMaps(wg *sync.WaitGroup) {
|
||||
}
|
||||
switch entry.Tag {
|
||||
case dwarf.TagArrayType, dwarf.TagBaseType, dwarf.TagClassType, dwarf.TagStructType, dwarf.TagUnionType, dwarf.TagConstType, dwarf.TagVolatileType, dwarf.TagRestrictType, dwarf.TagEnumerationType, dwarf.TagPointerType, dwarf.TagSubroutineType, dwarf.TagTypedef, dwarf.TagUnspecifiedType:
|
||||
name, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
continue
|
||||
if name, ok := entry.Val(dwarf.AttrName).(string); ok {
|
||||
if _, exists := bi.types[name]; !exists {
|
||||
bi.types[name] = entry.Offset
|
||||
}
|
||||
}
|
||||
if _, exists := bi.types[name]; !exists {
|
||||
bi.types[name] = entry.Offset
|
||||
reader.SkipChildren()
|
||||
case dwarf.TagVariable:
|
||||
if n, ok := entry.Val(dwarf.AttrName).(string); ok {
|
||||
bi.packageVars[n] = entry.Offset
|
||||
}
|
||||
case dwarf.TagSubprogram:
|
||||
lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
lowpc, ok1 := entry.Val(dwarf.AttrLowpc).(uint64)
|
||||
highpc, ok2 := entry.Val(dwarf.AttrHighpc).(uint64)
|
||||
if ok1 && ok2 {
|
||||
bi.functions = append(bi.functions, functionDebugInfo{lowpc, highpc, entry.Offset})
|
||||
}
|
||||
highpc, ok := entry.Val(dwarf.AttrHighpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
bi.functions = append(bi.functions, functionDebugInfo{lowpc, highpc, entry.Offset})
|
||||
reader.SkipChildren()
|
||||
}
|
||||
}
|
||||
sort.Sort(sortFunctionsDebugInfoByLowpc(bi.functions))
|
||||
|
||||
@ -650,18 +650,14 @@ func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) {
|
||||
}
|
||||
|
||||
func (scope *EvalScope) packageVarAddr(name string) (*Variable, error) {
|
||||
reader := scope.DwarfReader()
|
||||
for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for n, off := range scope.BinInfo.packageVars {
|
||||
if n == name || strings.HasSuffix(n, "/"+name) {
|
||||
reader := scope.DwarfReader()
|
||||
reader.Seek(off)
|
||||
entry, err := reader.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return scope.extractVarInfoFromEntry(entry, reader)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user