Commit d3946f75 authored by Hana Kim's avatar Hana Kim Committed by Hyang-Ah Hana Kim

internal/trace: remove backlinks from span/task end to start

This is an updated version of golang.org/cl/96395, with the fix to
TestUserSpan.

This reverts commit 7b6f6267e90a8e4eab37a3f2164ba882e6222adb.

Change-Id: I31eec8ba0997f9178dffef8dac608e731ab70872
Reviewed-on: https://go-review.googlesource.com/98236
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarHeschi Kreinick <heschi@google.com>
parent 83e41b3e
...@@ -152,6 +152,65 @@ type annotationAnalysisResult struct { ...@@ -152,6 +152,65 @@ type annotationAnalysisResult struct {
gcEvents []*trace.Event // GCStartevents, sorted gcEvents []*trace.Event // GCStartevents, sorted
} }
type activeSpanTracker struct {
stacks map[uint64][]*trace.Event // goid to stack of active span start events
}
func (t *activeSpanTracker) top(goid uint64) *trace.Event {
if t.stacks == nil {
return nil
}
stk := t.stacks[goid]
if len(stk) == 0 {
return nil
}
return stk[len(stk)-1]
}
func (t *activeSpanTracker) addSpanEvent(ev *trace.Event, task *taskDesc) *spanDesc {
if ev.Type != trace.EvUserSpan {
return nil
}
if t.stacks == nil {
t.stacks = make(map[uint64][]*trace.Event)
}
goid := ev.G
stk := t.stacks[goid]
var sd *spanDesc
switch mode := ev.Args[1]; mode {
case 0: // span start
t.stacks[goid] = append(stk, ev) // push
sd = &spanDesc{
name: ev.SArgs[0],
task: task,
goid: goid,
start: ev,
end: ev.Link,
}
case 1: // span end
if n := len(stk); n > 0 {
stk = stk[:n-1] // pop
} else {
// There is no matching span start event; can happen if the span start was before tracing.
sd = &spanDesc{
name: ev.SArgs[0],
task: task,
goid: goid,
start: nil,
end: ev,
}
}
if len(stk) == 0 {
delete(t.stacks, goid)
} else {
t.stacks[goid] = stk
}
}
return sd
}
// analyzeAnnotations analyzes user annotation events and // analyzeAnnotations analyzes user annotation events and
// returns the task descriptors keyed by internal task id. // returns the task descriptors keyed by internal task id.
func analyzeAnnotations() (annotationAnalysisResult, error) { func analyzeAnnotations() (annotationAnalysisResult, error) {
...@@ -166,14 +225,14 @@ func analyzeAnnotations() (annotationAnalysisResult, error) { ...@@ -166,14 +225,14 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
} }
tasks := allTasks{} tasks := allTasks{}
activeSpans := map[uint64][]*trace.Event{} // goid to active span start events
var gcEvents []*trace.Event var gcEvents []*trace.Event
var activeSpans activeSpanTracker
for _, ev := range events { for _, ev := range events {
goid := ev.G goid := ev.G
switch typ := ev.Type; typ { switch typ := ev.Type; typ {
case trace.EvUserTaskCreate, trace.EvUserTaskEnd, trace.EvUserLog, trace.EvUserSpan: case trace.EvUserTaskCreate, trace.EvUserTaskEnd, trace.EvUserLog:
taskid := ev.Args[0] taskid := ev.Args[0]
task := tasks.task(taskid) task := tasks.task(taskid)
task.addEvent(ev) task.addEvent(ev)
...@@ -189,18 +248,13 @@ func analyzeAnnotations() (annotationAnalysisResult, error) { ...@@ -189,18 +248,13 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
} }
} }
if typ == trace.EvUserSpan { case trace.EvUserSpan:
mode := ev.Args[1] taskid := ev.Args[0]
spans := activeSpans[goid] task := tasks.task(taskid)
if mode == 0 { // start task.addEvent(ev)
activeSpans[goid] = append(spans, ev) // push sd := activeSpans.addSpanEvent(ev, task)
} else { // end if task != nil && sd != nil {
if n := len(spans); n > 1 { task.spans = append(task.spans, sd)
activeSpans[goid] = spans[:n-1] // pop
} else if n == 1 {
delete(activeSpans, goid)
}
}
} }
case trace.EvGoCreate: case trace.EvGoCreate:
...@@ -209,11 +263,11 @@ func analyzeAnnotations() (annotationAnalysisResult, error) { ...@@ -209,11 +263,11 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
// //
// TODO(hyangah): the task info needs to propagate // TODO(hyangah): the task info needs to propagate
// to all decendents, not only to the immediate child. // to all decendents, not only to the immediate child.
spans := activeSpans[goid] s := activeSpans.top(goid)
if len(spans) == 0 { if s == nil {
continue continue
} }
taskid := spans[len(spans)-1].Args[0] taskid := s.Args[0]
task := tasks.task(taskid) task := tasks.task(taskid)
task.addEvent(ev) task.addEvent(ev)
...@@ -326,21 +380,6 @@ func (task *taskDesc) addEvent(ev *trace.Event) { ...@@ -326,21 +380,6 @@ func (task *taskDesc) addEvent(ev *trace.Event) {
task.create = ev task.create = ev
case trace.EvUserTaskEnd: case trace.EvUserTaskEnd:
task.end = ev task.end = ev
case trace.EvUserSpan:
if mode := ev.Args[1]; mode == 0 { // start
task.spans = append(task.spans, &spanDesc{
name: ev.SArgs[0],
task: task,
goid: ev.G,
start: ev,
end: ev.Link})
} else if ev.Link == nil { // span end without matching start
task.spans = append(task.spans, &spanDesc{
name: ev.SArgs[0],
task: task,
goid: ev.G,
end: ev})
}
} }
} }
......
...@@ -56,8 +56,7 @@ type Event struct { ...@@ -56,8 +56,7 @@ type Event struct {
// for GoSysExit: the next GoStart // for GoSysExit: the next GoStart
// for GCMarkAssistStart: the associated GCMarkAssistDone // for GCMarkAssistStart: the associated GCMarkAssistDone
// for UserTaskCreate: the UserTaskEnd // for UserTaskCreate: the UserTaskEnd
// for UsetTaskEnd: the UserTaskCreate // for UserSpan: if the start span, the corresponding UserSpan end event
// for UserSpan: the corresponding span start or end event
Link *Event Link *Event
} }
...@@ -810,9 +809,10 @@ func postProcessTrace(ver int, events []*Event) error { ...@@ -810,9 +809,10 @@ func postProcessTrace(ver int, events []*Event) error {
} }
tasks[ev.Args[0]] = ev tasks[ev.Args[0]] = ev
case EvUserTaskEnd: case EvUserTaskEnd:
if prevEv, ok := tasks[ev.Args[0]]; ok { taskid := ev.Args[0]
prevEv.Link = ev if taskCreateEv, ok := tasks[taskid]; ok {
ev.Link = prevEv taskCreateEv.Link = ev
delete(tasks, taskid)
} }
case EvUserSpan: case EvUserSpan:
mode := ev.Args[1] mode := ev.Args[1]
...@@ -828,7 +828,6 @@ func postProcessTrace(ver int, events []*Event) error { ...@@ -828,7 +828,6 @@ func postProcessTrace(ver int, events []*Event) error {
} }
// Link span start event with span end event // Link span start event with span end event
s.Link = ev s.Link = ev
ev.Link = s
if n > 1 { if n > 1 {
activeSpans[ev.G] = spans[:n-1] activeSpans[ev.G] = spans[:n-1]
......
...@@ -3,9 +3,11 @@ package trace_test ...@@ -3,9 +3,11 @@ package trace_test
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"internal/trace" "internal/trace"
"reflect" "reflect"
. "runtime/trace" . "runtime/trace"
"strings"
"sync" "sync"
"testing" "testing"
) )
...@@ -102,13 +104,20 @@ func TestUserTaskSpan(t *testing.T) { ...@@ -102,13 +104,20 @@ func TestUserTaskSpan(t *testing.T) {
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{0}, true}, {trace.EvUserSpan, []string{"task0", "span0"}, []uint64{0}, true},
{trace.EvUserSpan, []string{"task0", "span1"}, []uint64{0}, true}, {trace.EvUserSpan, []string{"task0", "span1"}, []uint64{0}, true},
{trace.EvUserLog, []string{"task0", "key0", "0123456789abcdef"}, nil, false}, {trace.EvUserLog, []string{"task0", "key0", "0123456789abcdef"}, nil, false},
{trace.EvUserSpan, []string{"task0", "span1"}, []uint64{1}, true}, {trace.EvUserSpan, []string{"task0", "span1"}, []uint64{1}, false},
{trace.EvUserSpan, []string{"task0", "span0"}, []uint64{1}, true}, {trace.EvUserSpan, []string{"task0", "span0"}, []uint64{1}, false},
{trace.EvUserTaskEnd, []string{"task0"}, nil, true}, {trace.EvUserTaskEnd, []string{"task0"}, nil, false},
{trace.EvUserSpan, []string{"", "pre-existing span"}, []uint64{1}, false}, {trace.EvUserSpan, []string{"", "pre-existing span"}, []uint64{1}, false},
{trace.EvUserSpan, []string{"", "post-existing span"}, []uint64{0}, false}, {trace.EvUserSpan, []string{"", "post-existing span"}, []uint64{0}, false},
} }
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Errorf("Got user span related events %+v\nwant: %+v", got, want) pretty := func(data []testData) string {
var s strings.Builder
for _, d := range data {
s.WriteString(fmt.Sprintf("\t%+v\n", d))
}
return s.String()
}
t.Errorf("Got user span related events\n%+v\nwant:\n%+v", pretty(got), pretty(want))
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment