mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 01:27:16 +08:00
proc/native/linuc: Better native.Process.stop performance (#1874)
* 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 #1549
This commit is contained in:
committed by
GitHub
parent
17e70a908e
commit
e9b2da17cb
@ -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]
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
if !th.Stopped() {
|
||||
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.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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ type OSSpecificDetails struct {
|
||||
delayedSignal int
|
||||
registers sys.PtraceRegs
|
||||
running bool
|
||||
setbp bool
|
||||
}
|
||||
|
||||
func (t *Thread) stop() (err error) {
|
||||
|
||||
Reference in New Issue
Block a user