Skip to content

Commit

Permalink
proc/native/linuc: Better native.Process.stop performance (go-delve#1874
Browse files Browse the repository at this point in the history
)

* proc/native/linux: only set breakpoints on threads that receive SIGTRAP

* proc/native/linux: do not call (*Thread).Stopped inside (*Process).stop

(*Thread).Stopped is slow because it needs to open, read and parse a
file in /proc, we don't actually need to do that, we can just rely on
the value of Thread.os.running.

Benchmark before:

BenchmarkConditionalBreakpoints-4              1        12476166303 ns/op

Benchmark after:

BenchmarkConditionalBreakpoints-4   	       1	10403533675 ns/op

Conditional breakpoint evaluation: 1.24ms -> 1ms

Updates go-delve#1549
  • Loading branch information
aarzilli authored Mar 9, 2020
1 parent fd44c44 commit e2561f6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
52 changes: 41 additions & 11 deletions pkg/proc/native/proc_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,31 @@ func findExecutable(path string, pid int) string {
}

func (dbp *Process) trapWait(pid int) (*Thread, error) {
return dbp.trapWaitInternal(pid, false)
return dbp.trapWaitInternal(pid, 0)
}

func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) {
type trapWaitOptions uint8

const (
trapWaitHalt trapWaitOptions = 1 << iota
trapWaitNohang
)

func (dbp *Process) trapWaitInternal(pid int, options trapWaitOptions) (*Thread, error) {
halt := options&trapWaitHalt != 0
for {
wpid, status, err := dbp.wait(pid, 0)
wopt := 0
if options&trapWaitNohang != 0 {
wopt = sys.WNOHANG
}
wpid, status, err := dbp.wait(pid, wopt)
if err != nil {
return nil, fmt.Errorf("wait err %s %d", err, pid)
}
if wpid == 0 {
if options&trapWaitNohang != 0 {
return nil, nil
}
continue
}
th, ok := dbp.threads[wpid]
Expand Down Expand Up @@ -321,6 +336,9 @@ func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) {
}
if (halt && status.StopSignal() == sys.SIGSTOP) || (status.StopSignal() == sys.SIGTRAP) {
th.os.running = false
if status.StopSignal() == sys.SIGTRAP {
th.os.setbp = true
}
return th, nil
}

Expand Down Expand Up @@ -411,7 +429,7 @@ func (dbp *Process) exitGuard(err error) error {
return err
}
if status(dbp.pid, dbp.os.comm) == StatusZombie {
_, err := dbp.trapWaitInternal(-1, false)
_, err := dbp.trapWaitInternal(-1, 0)
return err
}

Expand Down Expand Up @@ -442,14 +460,26 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
if dbp.exited {
return &proc.ErrProcessExited{Pid: dbp.Pid()}
}

for _, th := range dbp.threads {
th.os.setbp = false
}
trapthread.os.setbp = true

// check if any other thread simultaneously received a SIGTRAP
for {
th, _ := dbp.trapWaitInternal(-1, trapWaitNohang)
if th == nil {
break
}
}

// stop all threads that are still running
for _, th := range dbp.threads {
if !th.Stopped() {
if th.os.running {
if err := th.stop(); err != nil {
return dbp.exitGuard(err)
}
} else {
// Thread is already in a trace stop but we didn't get the notification yet.
th.os.running = false
}
}

Expand All @@ -465,7 +495,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
if allstopped {
break
}
_, err := dbp.trapWaitInternal(-1, true)
_, err := dbp.trapWaitInternal(-1, trapWaitHalt)
if err != nil {
return err
}
Expand All @@ -475,9 +505,9 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
return err
}

// set breakpoints on all threads
// set breakpoints on SIGTRAP threads
for _, th := range dbp.threads {
if th.CurrentBreakpoint.Breakpoint == nil {
if th.CurrentBreakpoint.Breakpoint == nil && th.os.setbp {
if err := th.SetCurrentBreakpoint(true); err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/proc/native/threads_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type OSSpecificDetails struct {
delayedSignal int
registers sys.PtraceRegs
running bool
setbp bool
}

func (t *Thread) stop() (err error) {
Expand Down

0 comments on commit e2561f6

Please sign in to comment.