]> Cypherpunks repositories - gostls13.git/commitdiff
internal/trace: remove backlinks from span/task end to start
authorHana Kim <hakim@google.com>
Thu, 22 Feb 2018 18:27:39 +0000 (13:27 -0500)
committerHyang-Ah Hana Kim <hyangah@gmail.com>
Fri, 2 Mar 2018 20:15:57 +0000 (20:15 +0000)
Even though undocumented, the assumption is the Event's link field
points to the following event in the future. The new span/task event
processing breaks the assumption.

Change-Id: I4ce2f30c67c4f525ec0a121a7e43d8bdd2ec3f77
Reviewed-on: https://go-review.googlesource.com/96395
Reviewed-by: Heschi Kreinick <heschi@google.com>
src/cmd/trace/annotations.go
src/internal/trace/parser.go

index 91cdd4d1980c6013372b01797f210c104f066079..c7c0b637c71d2c53e31cb2d4365c4899a79b7938 100644 (file)
@@ -152,6 +152,65 @@ type annotationAnalysisResult struct {
        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
 // returns the task descriptors keyed by internal task id.
 func analyzeAnnotations() (annotationAnalysisResult, error) {
@@ -166,14 +225,14 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
        }
 
        tasks := allTasks{}
-       activeSpans := map[uint64][]*trace.Event{} // goid to active span start events
        var gcEvents []*trace.Event
+       var activeSpans activeSpanTracker
 
        for _, ev := range events {
                goid := ev.G
 
                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]
                        task := tasks.task(taskid)
                        task.addEvent(ev)
@@ -189,18 +248,13 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
                                }
                        }
 
-                       if typ == trace.EvUserSpan {
-                               mode := ev.Args[1]
-                               spans := activeSpans[goid]
-                               if mode == 0 { // start
-                                       activeSpans[goid] = append(spans, ev) // push
-                               } else { // end
-                                       if n := len(spans); n > 1 {
-                                               activeSpans[goid] = spans[:n-1] // pop
-                                       } else if n == 1 {
-                                               delete(activeSpans, goid)
-                                       }
-                               }
+               case trace.EvUserSpan:
+                       taskid := ev.Args[0]
+                       task := tasks.task(taskid)
+                       task.addEvent(ev)
+                       sd := activeSpans.addSpanEvent(ev, task)
+                       if task != nil && sd != nil {
+                               task.spans = append(task.spans, sd)
                        }
 
                case trace.EvGoCreate:
@@ -209,11 +263,11 @@ func analyzeAnnotations() (annotationAnalysisResult, error) {
                        //
                        // TODO(hyangah): the task info needs to propagate
                        // to all decendents, not only to the immediate child.
-                       spans := activeSpans[goid]
-                       if len(spans) == 0 {
+                       s := activeSpans.top(goid)
+                       if s == nil {
                                continue
                        }
-                       taskid := spans[len(spans)-1].Args[0]
+                       taskid := s.Args[0]
                        task := tasks.task(taskid)
                        task.addEvent(ev)
 
@@ -326,21 +380,6 @@ func (task *taskDesc) addEvent(ev *trace.Event) {
                task.create = ev
        case trace.EvUserTaskEnd:
                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})
-               }
        }
 }
 
index 155c23940a01e76bf66b99355dcba99792a595a4..29ba73c76165185b6f3c01a96b3bd0a099b93d88 100644 (file)
@@ -56,8 +56,7 @@ type Event struct {
        // for GoSysExit: the next GoStart
        // for GCMarkAssistStart: the associated GCMarkAssistDone
        // for UserTaskCreate: the UserTaskEnd
-       // for UsetTaskEnd: the UserTaskCreate
-       // for UserSpan: the corresponding span start or end event
+       // for UserSpan: if the start span, the corresponding UserSpan end event
        Link *Event
 }
 
@@ -810,9 +809,10 @@ func postProcessTrace(ver int, events []*Event) error {
                        }
                        tasks[ev.Args[0]] = ev
                case EvUserTaskEnd:
-                       if prevEv, ok := tasks[ev.Args[0]]; ok {
-                               prevEv.Link = ev
-                               ev.Link = prevEv
+                       taskid := ev.Args[0]
+                       if taskCreateEv, ok := tasks[taskid]; ok {
+                               taskCreateEv.Link = ev
+                               delete(tasks, taskid)
                        }
                case EvUserSpan:
                        mode := ev.Args[1]
@@ -828,7 +828,6 @@ func postProcessTrace(ver int, events []*Event) error {
                                        }
                                        // Link span start event with span end event
                                        s.Link = ev
-                                       ev.Link = s
 
                                        if n > 1 {
                                                activeSpans[ev.G] = spans[:n-1]