Skip to content

Commit

Permalink
proc: avoid constructing unnecessary strings when evaluating variables
Browse files Browse the repository at this point in the history
Avoids constructing:

1. name of runtime.curg fields while executing parseG
2. the location expression while evaluating any variable.

Benchmark before:

BenchmarkConditionalBreakpoints-4   	       1	4953889884 ns/op

Benchmark after:

BenchmarkConditionalBreakpoints-4   	       1	4419775128 ns/op

Updates go-delve#1549
  • Loading branch information
aarzilli authored and derekparker committed Mar 31, 2020
1 parent da0f66e commit 43259b4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 22 deletions.
48 changes: 35 additions & 13 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -809,29 +809,51 @@ func (bi *BinaryInfo) LoadImageFromData(dwdata *dwarf.Data, debugFrameBytes, deb
bi.Images = append(bi.Images, image)
}

func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, string, error) {
func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, *locationExpr, error) {
a := entry.Val(attr)
if a == nil {
return nil, "", fmt.Errorf("no location attribute %s", attr)
return nil, nil, fmt.Errorf("no location attribute %s", attr)
}
if instr, ok := a.([]byte); ok {
var descr bytes.Buffer
fmt.Fprintf(&descr, "[block] ")
op.PrettyPrint(&descr, instr)
return instr, descr.String(), nil
return instr, &locationExpr{isBlock: true, instr: instr}, nil
}
off, ok := a.(int64)
if !ok {
return nil, "", fmt.Errorf("could not interpret location attribute %s", attr)
return nil, nil, fmt.Errorf("could not interpret location attribute %s", attr)
}
instr := bi.loclistEntry(off, pc)
if instr == nil {
return nil, "", fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc)
return nil, nil, fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc)
}
return instr, &locationExpr{pc: pc, off: off, instr: instr}, nil
}

type locationExpr struct {
isBlock bool
isEscaped bool
off int64
pc uint64
instr []byte
}

func (le *locationExpr) String() string {
if le == nil {
return ""
}
var descr bytes.Buffer
fmt.Fprintf(&descr, "[%#x:%#x] ", off, pc)
op.PrettyPrint(&descr, instr)
return instr, descr.String(), nil

if le.isBlock {
fmt.Fprintf(&descr, "[block] ")
op.PrettyPrint(&descr, le.instr)
} else {
fmt.Fprintf(&descr, "[%#x:%#x] ", le.off, le.pc)
op.PrettyPrint(&descr, le.instr)
}

if le.isEscaped {
fmt.Fprintf(&descr, " (escaped)")
}
return descr.String()
}

// LocationCovers returns the list of PC addresses that is covered by the
Expand Down Expand Up @@ -877,10 +899,10 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
// This will either be an int64 address or a slice of Pieces for locations
// that don't correspond to a single memory address (registers, composite
// locations).
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, string, error) {
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, *locationExpr, error) {
instr, descr, err := bi.locationExpr(entry, attr, pc)
if err != nil {
return 0, nil, "", err
return 0, nil, nil, err
}
addr, pieces, err := op.ExecuteStackProgram(regs, instr, bi.Arch.PtrSize())
return addr, pieces, descr, err
Expand Down
3 changes: 2 additions & 1 deletion pkg/proc/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
}
v.Name = name[1:]
v.Flags |= VariableEscaped
v.LocationExpr = locationExpr + " (escaped)"
locationExpr.isEscaped = true
v.LocationExpr = locationExpr
v.DeclLine = declLine
vars[i] = v
}
Expand Down
12 changes: 5 additions & 7 deletions pkg/proc/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ type Variable struct {
loaded bool
Unreadable error

LocationExpr string // location expression
DeclLine int64 // line number of this variable's declaration
LocationExpr *locationExpr // location expression
DeclLine int64 // line number of this variable's declaration
}

// LoadConfig controls how variables are loaded from the targets memory.
Expand Down Expand Up @@ -441,8 +441,6 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
return nil, err
}

name := ""

if deref {
typ = &godwarf.PtrType{
CommonType: godwarf.CommonType{
Expand All @@ -453,11 +451,9 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
},
Type: typ,
}
} else {
name = "runtime.curg"
}

return newVariableFromThread(thread, name, gaddr, typ), nil
return newVariableFromThread(thread, "", gaddr, typ), nil
}

// Defer returns the top-most defer of the goroutine.
Expand Down Expand Up @@ -851,6 +847,8 @@ func (v *Variable) parseG() (*G, error) {

f, l, fn := v.bi.PCToLine(uint64(pc))

v.Name = "runtime.curg"

g := &G{
ID: int(id),
GoPC: uint64(gopc),
Expand Down
2 changes: 1 addition & 1 deletion service/api/conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func ConvertVar(v *proc.Variable) *Variable {
Flags: VariableFlags(v.Flags),
Base: v.Base,

LocationExpr: v.LocationExpr,
LocationExpr: v.LocationExpr.String(),
DeclLine: v.DeclLine,
}

Expand Down

0 comments on commit 43259b4

Please sign in to comment.