mirror of
https://github.com/golang/go
synced 2024-09-29 07:24:32 -06:00
cmd/trace: remove unrelated arrows in task-oriented traceview
Also grey out instants that represent events occurred outside the task's span. Furthermore, if the unrelated instants represent user annotation events but not for the task of the interest, skip rendering completely. This helps users to focus on the task-related events better. UI screen shot: https://gist.github.com/hyangah/1df5d2c8f429fd933c481e9636b89b55#file-golang-org_cl_99035 Change-Id: I2b5aef41584c827f8c1e915d0d8e5c95fe2b4b65 Reviewed-on: https://go-review.googlesource.com/99035 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> Run-TryBot: Heschi Kreinick <heschi@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
53c416396f
commit
476f71c958
@ -446,12 +446,42 @@ func (task *taskDesc) overlappingGCDuration(evs []*trace.Event) (overlapping tim
|
||||
return overlapping
|
||||
}
|
||||
|
||||
// overlappingInstant returns true if the instantaneous event, ev, occurred during
|
||||
// any of the task's span if ev is a goroutine-local event, or overlaps with the
|
||||
// task's lifetime if ev is a global event.
|
||||
func (task *taskDesc) overlappingInstant(ev *trace.Event) bool {
|
||||
if isUserAnnotationEvent(ev) && task.id != ev.Args[0] {
|
||||
return false // not this task's user event.
|
||||
}
|
||||
|
||||
ts := ev.Ts
|
||||
taskStart := task.firstTimestamp()
|
||||
taskEnd := task.lastTimestamp()
|
||||
if ts < taskStart || taskEnd < ts {
|
||||
return false
|
||||
}
|
||||
if ev.P == trace.GCP {
|
||||
return true
|
||||
}
|
||||
|
||||
// Goroutine local event. Check whether there are spans overlapping with the event.
|
||||
goid := ev.G
|
||||
for _, span := range task.spans {
|
||||
if span.goid != goid {
|
||||
continue
|
||||
}
|
||||
if span.firstTimestamp() <= ts && ts <= span.lastTimestamp() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// overlappingDuration returns whether the durational event, ev, overlaps with
|
||||
// any of the task's span if ev is a goroutine-local event, or overlaps with
|
||||
// the task's lifetime if ev is a global event. It returns the overlapping time
|
||||
// as well.
|
||||
func (task *taskDesc) overlappingDuration(ev *trace.Event) (time.Duration, bool) {
|
||||
// TODO: check whether ev is a 'durational' event.
|
||||
start := ev.Ts
|
||||
end := lastTimestamp()
|
||||
if ev.Link != nil {
|
||||
@ -463,9 +493,13 @@ func (task *taskDesc) overlappingDuration(ev *trace.Event) (time.Duration, bool)
|
||||
}
|
||||
|
||||
goid := ev.G
|
||||
goid2 := ev.G
|
||||
if ev.Link != nil {
|
||||
goid2 = ev.Link.G
|
||||
}
|
||||
|
||||
// This event is a global event (G=0)
|
||||
if goid == 0 {
|
||||
// This event is a global GC event
|
||||
if ev.P == trace.GCP {
|
||||
taskStart := task.firstTimestamp()
|
||||
taskEnd := task.lastTimestamp()
|
||||
o := overlappingDuration(taskStart, taskEnd, start, end)
|
||||
@ -476,7 +510,7 @@ func (task *taskDesc) overlappingDuration(ev *trace.Event) (time.Duration, bool)
|
||||
var overlapping time.Duration
|
||||
var lastSpanEnd int64 // the end of previous overlapping span
|
||||
for _, span := range task.spans {
|
||||
if span.goid != goid {
|
||||
if span.goid != goid && span.goid != goid2 {
|
||||
continue
|
||||
}
|
||||
spanStart, spanEnd := span.firstTimestamp(), span.lastTimestamp()
|
||||
@ -925,3 +959,11 @@ func describeEvent(ev *trace.Event) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func isUserAnnotationEvent(ev *trace.Event) bool {
|
||||
switch ev.Type {
|
||||
case trace.EvUserLog, trace.EvUserSpan, trace.EvUserTaskCreate, trace.EvUserTaskEnd:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -916,6 +916,23 @@ func (ctx *traceContext) emitThreadCounters(ev *trace.Event) {
|
||||
}
|
||||
|
||||
func (ctx *traceContext) emitInstant(ev *trace.Event, name, category string) {
|
||||
cname := ""
|
||||
if ctx.mode == taskTraceview && ev.G != 0 {
|
||||
overlapping := false
|
||||
for _, task := range ctx.tasks {
|
||||
if task.overlappingInstant(ev) {
|
||||
overlapping = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// grey out or skip if non-overlapping instant.
|
||||
if !overlapping {
|
||||
if isUserAnnotationEvent(ev) {
|
||||
return // don't display unrelated task events.
|
||||
}
|
||||
cname = "grey"
|
||||
}
|
||||
}
|
||||
var arg interface{}
|
||||
if ev.Type == trace.EvProcStart {
|
||||
type Arg struct {
|
||||
@ -931,6 +948,7 @@ func (ctx *traceContext) emitInstant(ev *trace.Event, name, category string) {
|
||||
Time: ctx.time(ev),
|
||||
Tid: ctx.proc(ev),
|
||||
Stack: ctx.stack(ev.Stk),
|
||||
Cname: cname,
|
||||
Arg: arg})
|
||||
}
|
||||
|
||||
@ -950,6 +968,20 @@ func (ctx *traceContext) emitArrow(ev *trace.Event, name string) {
|
||||
ctx.emitInstant(&trace.Event{P: ev.P, Ts: ev.Ts}, "unblock", "")
|
||||
}
|
||||
|
||||
if ctx.mode == taskTraceview {
|
||||
overlapping := false
|
||||
// skip non-overlapping arrows.
|
||||
for _, task := range ctx.tasks {
|
||||
if _, overlapped := task.overlappingDuration(ev); overlapped {
|
||||
overlapping = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !overlapping {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.arrowSeq++
|
||||
ctx.emit(&ViewerEvent{Name: name, Phase: "s", Tid: ctx.proc(ev), ID: ctx.arrowSeq, Time: ctx.time(ev), Stack: ctx.stack(ev.Stk)})
|
||||
ctx.emit(&ViewerEvent{Name: name, Phase: "t", Tid: ctx.proc(ev.Link), ID: ctx.arrowSeq, Time: ctx.time(ev.Link)})
|
||||
|
Loading…
Reference in New Issue
Block a user