diff options
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/trace/annotations.go | 204 | ||||
| -rw-r--r-- | src/cmd/trace/annotations_test.go | 110 | ||||
| -rw-r--r-- | src/cmd/trace/main.go | 2 | ||||
| -rw-r--r-- | src/cmd/trace/pprof.go | 34 | ||||
| -rw-r--r-- | src/cmd/trace/trace.go | 24 |
5 files changed, 187 insertions, 187 deletions
diff --git a/src/cmd/trace/annotations.go b/src/cmd/trace/annotations.go index 0d2bdfcbba..5f672de3b4 100644 --- a/src/cmd/trace/annotations.go +++ b/src/cmd/trace/annotations.go @@ -18,8 +18,8 @@ import ( func init() { http.HandleFunc("/usertasks", httpUserTasks) http.HandleFunc("/usertask", httpUserTask) - http.HandleFunc("/userspans", httpUserSpans) - http.HandleFunc("/userspan", httpUserSpan) + http.HandleFunc("/userregions", httpUserRegions) + http.HandleFunc("/userregion", httpUserRegion) } // httpUserTasks reports all tasks found in the trace. @@ -59,46 +59,46 @@ func httpUserTasks(w http.ResponseWriter, r *http.Request) { } } -func httpUserSpans(w http.ResponseWriter, r *http.Request) { +func httpUserRegions(w http.ResponseWriter, r *http.Request) { res, err := analyzeAnnotations() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - allSpans := res.spans + allRegions := res.regions - summary := make(map[spanTypeID]spanStats) - for id, spans := range allSpans { + summary := make(map[regionTypeID]regionStats) + for id, regions := range allRegions { stats, ok := summary[id] if !ok { - stats.spanTypeID = id + stats.regionTypeID = id } - for _, s := range spans { + for _, s := range regions { stats.add(s) } summary[id] = stats } - // Sort spans by pc and name - userSpans := make([]spanStats, 0, len(summary)) + // Sort regions by pc and name + userRegions := make([]regionStats, 0, len(summary)) for _, stats := range summary { - userSpans = append(userSpans, stats) + userRegions = append(userRegions, stats) } - sort.Slice(userSpans, func(i, j int) bool { - if userSpans[i].Type != userSpans[j].Type { - return userSpans[i].Type < userSpans[j].Type + sort.Slice(userRegions, func(i, j int) bool { + if userRegions[i].Type != userRegions[j].Type { + return userRegions[i].Type < userRegions[j].Type } - return userSpans[i].Frame.PC < userSpans[j].Frame.PC + return userRegions[i].Frame.PC < userRegions[j].Frame.PC }) // Emit table. - err = templUserSpanTypes.Execute(w, userSpans) + err = templUserRegionTypes.Execute(w, userRegions) if err != nil { http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) return } } -func httpUserSpan(w http.ResponseWriter, r *http.Request) { - filter, err := newSpanFilter(r) +func httpUserRegion(w http.ResponseWriter, r *http.Request) { + filter, err := newRegionFilter(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -108,13 +108,13 @@ func httpUserSpan(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - allSpans := res.spans + allRegions := res.regions - var data []spanDesc + var data []regionDesc var maxTotal int64 - for id, spans := range allSpans { - for _, s := range spans { + for id, regions := range allRegions { + for _, s := range regions { if !filter.match(id, s) { continue } @@ -126,7 +126,7 @@ func httpUserSpan(w http.ResponseWriter, r *http.Request) { } sortby := r.FormValue("sortby") - _, ok := reflect.TypeOf(spanDesc{}).FieldByNameFunc(func(s string) bool { + _, ok := reflect.TypeOf(regionDesc{}).FieldByNameFunc(func(s string) bool { return s == sortby }) if !ok { @@ -138,9 +138,9 @@ func httpUserSpan(w http.ResponseWriter, r *http.Request) { return ival > jval }) - err = templUserSpanType.Execute(w, struct { + err = templUserRegionType.Execute(w, struct { MaxTotal int64 - Data []spanDesc + Data []regionDesc Name string }{ MaxTotal: maxTotal, @@ -193,9 +193,9 @@ func httpUserTask(w http.ResponseWriter, r *http.Request) { if !filter.match(task) { continue } - // merge events in the task.events and task.spans.Start + // merge events in the task.events and task.regions.Start rawEvents := append([]*trace.Event{}, task.events...) - for _, s := range task.spans { + for _, s := range task.regions { if s.Start != nil { rawEvents = append(rawEvents, s.Start) } @@ -254,12 +254,12 @@ func httpUserTask(w http.ResponseWriter, r *http.Request) { } type annotationAnalysisResult struct { - tasks map[uint64]*taskDesc // tasks - spans map[spanTypeID][]spanDesc // spans - gcEvents []*trace.Event // GCStartevents, sorted + tasks map[uint64]*taskDesc // tasks + regions map[regionTypeID][]regionDesc // regions + gcEvents []*trace.Event // GCStartevents, sorted } -type spanTypeID struct { +type regionTypeID struct { Frame trace.Frame // top frame Type string } @@ -278,7 +278,7 @@ func analyzeAnnotations() (annotationAnalysisResult, error) { } tasks := allTasks{} - spans := map[spanTypeID][]spanDesc{} + regions := map[regionTypeID][]regionDesc{} var gcEvents []*trace.Event for _, ev := range events { @@ -303,38 +303,38 @@ func analyzeAnnotations() (annotationAnalysisResult, error) { gcEvents = append(gcEvents, ev) } } - // combine span info. + // combine region info. analyzeGoroutines(events) for goid, stats := range gs { // gs is a global var defined in goroutines.go as a result // of analyzeGoroutines. TODO(hyangah): fix this not to depend // on a 'global' var. - for _, s := range stats.Spans { + for _, s := range stats.Regions { if s.TaskID != 0 { task := tasks.task(s.TaskID) task.goroutines[goid] = struct{}{} - task.spans = append(task.spans, spanDesc{UserSpanDesc: s, G: goid}) + task.regions = append(task.regions, regionDesc{UserRegionDesc: s, G: goid}) } var frame trace.Frame if s.Start != nil { frame = *s.Start.Stk[0] } - id := spanTypeID{Frame: frame, Type: s.Name} - spans[id] = append(spans[id], spanDesc{UserSpanDesc: s, G: goid}) + id := regionTypeID{Frame: frame, Type: s.Name} + regions[id] = append(regions[id], regionDesc{UserRegionDesc: s, G: goid}) } } - // sort spans in tasks based on the timestamps. + // sort regions in tasks based on the timestamps. for _, task := range tasks { - sort.SliceStable(task.spans, func(i, j int) bool { - si, sj := task.spans[i].firstTimestamp(), task.spans[j].firstTimestamp() + sort.SliceStable(task.regions, func(i, j int) bool { + si, sj := task.regions[i].firstTimestamp(), task.regions[j].firstTimestamp() if si != sj { return si < sj } - return task.spans[i].lastTimestamp() < task.spans[i].lastTimestamp() + return task.regions[i].lastTimestamp() < task.regions[i].lastTimestamp() }) } - return annotationAnalysisResult{tasks: tasks, spans: spans, gcEvents: gcEvents}, nil + return annotationAnalysisResult{tasks: tasks, regions: regions, gcEvents: gcEvents}, nil } // taskDesc represents a task. @@ -342,7 +342,7 @@ type taskDesc struct { name string // user-provided task name id uint64 // internal task id events []*trace.Event // sorted based on timestamp. - spans []spanDesc // associated spans, sorted based on the start timestamp and then the last timestamp. + regions []regionDesc // associated regions, sorted based on the start timestamp and then the last timestamp. goroutines map[uint64]struct{} // involved goroutines create *trace.Event // Task create event @@ -367,8 +367,8 @@ func (task *taskDesc) String() string { fmt.Fprintf(wb, "task %d:\t%s\n", task.id, task.name) fmt.Fprintf(wb, "\tstart: %v end: %v complete: %t\n", task.firstTimestamp(), task.lastTimestamp(), task.complete()) fmt.Fprintf(wb, "\t%d goroutines\n", len(task.goroutines)) - fmt.Fprintf(wb, "\t%d spans:\n", len(task.spans)) - for _, s := range task.spans { + fmt.Fprintf(wb, "\t%d regions:\n", len(task.regions)) + for _, s := range task.regions { fmt.Fprintf(wb, "\t\t%s(goid=%d)\n", s.Name, s.G) } if task.parent != nil { @@ -382,10 +382,10 @@ func (task *taskDesc) String() string { return wb.String() } -// spanDesc represents a span. -type spanDesc struct { - *trace.UserSpanDesc - G uint64 // id of goroutine where the span was defined +// regionDesc represents a region. +type regionDesc struct { + *trace.UserRegionDesc + G uint64 // id of goroutine where the region was defined } type allTasks map[uint64]*taskDesc @@ -473,8 +473,8 @@ func (task *taskDesc) duration() time.Duration { return time.Duration(task.lastTimestamp()-task.firstTimestamp()) * time.Nanosecond } -func (span *spanDesc) duration() time.Duration { - return time.Duration(span.lastTimestamp()-span.firstTimestamp()) * time.Nanosecond +func (region *regionDesc) duration() time.Duration { + return time.Duration(region.lastTimestamp()-region.firstTimestamp()) * time.Nanosecond } // overlappingGCDuration returns the sum of GC period overlapping with the task's lifetime. @@ -493,7 +493,7 @@ func (task *taskDesc) overlappingGCDuration(evs []*trace.Event) (overlapping tim } // 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 +// any of the task's region 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] { @@ -510,13 +510,13 @@ func (task *taskDesc) overlappingInstant(ev *trace.Event) bool { return true } - // Goroutine local event. Check whether there are spans overlapping with the event. + // Goroutine local event. Check whether there are regions overlapping with the event. goid := ev.G - for _, span := range task.spans { - if span.G != goid { + for _, region := range task.regions { + if region.G != goid { continue } - if span.firstTimestamp() <= ts && ts <= span.lastTimestamp() { + if region.firstTimestamp() <= ts && ts <= region.lastTimestamp() { return true } } @@ -524,7 +524,7 @@ func (task *taskDesc) overlappingInstant(ev *trace.Event) bool { } // 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 +// any of the task's region 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) { @@ -552,21 +552,21 @@ func (task *taskDesc) overlappingDuration(ev *trace.Event) (time.Duration, bool) return o, o > 0 } - // Goroutine local event. Check whether there are spans overlapping with the event. + // Goroutine local event. Check whether there are regions overlapping with the event. var overlapping time.Duration - var lastSpanEnd int64 // the end of previous overlapping span - for _, span := range task.spans { - if span.G != goid && span.G != goid2 { + var lastRegionEnd int64 // the end of previous overlapping region + for _, region := range task.regions { + if region.G != goid && region.G != goid2 { continue } - spanStart, spanEnd := span.firstTimestamp(), span.lastTimestamp() - if spanStart < lastSpanEnd { // skip nested spans + regionStart, regionEnd := region.firstTimestamp(), region.lastTimestamp() + if regionStart < lastRegionEnd { // skip nested regions continue } - if o := overlappingDuration(spanStart, spanEnd, start, end); o > 0 { + if o := overlappingDuration(regionStart, regionEnd, start, end); o > 0 { // overlapping. - lastSpanEnd = spanEnd + lastRegionEnd = regionEnd overlapping += o } } @@ -602,22 +602,22 @@ func (task *taskDesc) lastEvent() *trace.Event { return nil } -// firstTimestamp returns the timestamp of span start event. -// If the span's start event is not present in the trace, +// firstTimestamp returns the timestamp of region start event. +// If the region's start event is not present in the trace, // the first timestamp of the trace will be returned. -func (span *spanDesc) firstTimestamp() int64 { - if span.Start != nil { - return span.Start.Ts +func (region *regionDesc) firstTimestamp() int64 { + if region.Start != nil { + return region.Start.Ts } return firstTimestamp() } -// lastTimestamp returns the timestamp of span end event. -// If the span's end event is not present in the trace, +// lastTimestamp returns the timestamp of region end event. +// If the region's end event is not present in the trace, // the last timestamp of the trace will be returned. -func (span *spanDesc) lastTimestamp() int64 { - if span.End != nil { - return span.End.Ts +func (region *regionDesc) lastTimestamp() int64 { + if region.End != nil { + return region.End.Ts } return lastTimestamp() } @@ -721,7 +721,7 @@ func newTaskFilter(r *http.Request) (*taskFilter, error) { func taskMatches(t *taskDesc, text string) bool { for _, ev := range t.events { switch ev.Type { - case trace.EvUserTaskCreate, trace.EvUserSpan, trace.EvUserLog: + case trace.EvUserTaskCreate, trace.EvUserRegion, trace.EvUserLog: for _, s := range ev.SArgs { if strings.Contains(s, text) { return true @@ -732,12 +732,12 @@ func taskMatches(t *taskDesc, text string) bool { return false } -type spanFilter struct { +type regionFilter struct { name string - cond []func(spanTypeID, spanDesc) bool + cond []func(regionTypeID, regionDesc) bool } -func (f *spanFilter) match(id spanTypeID, s spanDesc) bool { +func (f *regionFilter) match(id regionTypeID, s regionDesc) bool { for _, c := range f.cond { if !c(id, s) { return false @@ -746,42 +746,42 @@ func (f *spanFilter) match(id spanTypeID, s spanDesc) bool { return true } -func newSpanFilter(r *http.Request) (*spanFilter, error) { +func newRegionFilter(r *http.Request) (*regionFilter, error) { if err := r.ParseForm(); err != nil { return nil, err } var name []string - var conditions []func(spanTypeID, spanDesc) bool + var conditions []func(regionTypeID, regionDesc) bool param := r.Form if typ, ok := param["type"]; ok && len(typ) > 0 { name = append(name, "type="+typ[0]) - conditions = append(conditions, func(id spanTypeID, s spanDesc) bool { + conditions = append(conditions, func(id regionTypeID, s regionDesc) bool { return id.Type == typ[0] }) } if pc, err := strconv.ParseUint(r.FormValue("pc"), 16, 64); err == nil { name = append(name, fmt.Sprintf("pc=%x", pc)) - conditions = append(conditions, func(id spanTypeID, s spanDesc) bool { + conditions = append(conditions, func(id regionTypeID, s regionDesc) bool { return id.Frame.PC == pc }) } if lat, err := time.ParseDuration(r.FormValue("latmin")); err == nil { name = append(name, fmt.Sprintf("latency >= %s", lat)) - conditions = append(conditions, func(_ spanTypeID, s spanDesc) bool { + conditions = append(conditions, func(_ regionTypeID, s regionDesc) bool { return s.duration() >= lat }) } if lat, err := time.ParseDuration(r.FormValue("latmax")); err == nil { name = append(name, fmt.Sprintf("latency <= %s", lat)) - conditions = append(conditions, func(_ spanTypeID, s spanDesc) bool { + conditions = append(conditions, func(_ regionTypeID, s regionDesc) bool { return s.duration() <= lat }) } - return &spanFilter{name: strings.Join(name, ","), cond: conditions}, nil + return ®ionFilter{name: strings.Join(name, ","), cond: conditions}, nil } type durationHistogram struct { @@ -893,22 +893,22 @@ func (h *durationHistogram) String() string { return w.String() } -type spanStats struct { - spanTypeID +type regionStats struct { + regionTypeID Histogram durationHistogram } -func (s *spanStats) UserSpanURL() func(min, max time.Duration) string { +func (s *regionStats) UserRegionURL() func(min, max time.Duration) string { return func(min, max time.Duration) string { - return fmt.Sprintf("/userspan?type=%s&pc=%x&latmin=%v&latmax=%v", template.URLQueryEscaper(s.Type), s.Frame.PC, template.URLQueryEscaper(min), template.URLQueryEscaper(max)) + return fmt.Sprintf("/userregion?type=%s&pc=%x&latmin=%v&latmax=%v", template.URLQueryEscaper(s.Type), s.Frame.PC, template.URLQueryEscaper(min), template.URLQueryEscaper(max)) } } -func (s *spanStats) add(span spanDesc) { - s.Histogram.add(span.duration()) +func (s *regionStats) add(region regionDesc) { + s.Histogram.add(region.duration()) } -var templUserSpanTypes = template.Must(template.New("").Parse(` +var templUserRegionTypes = template.Must(template.New("").Parse(` <html> <style type="text/css"> .histoTime { @@ -920,15 +920,15 @@ var templUserSpanTypes = template.Must(template.New("").Parse(` <body> <table border="1" sortable="1"> <tr> -<th>Span type</th> +<th>Region type</th> <th>Count</th> <th>Duration distribution (complete tasks)</th> </tr> {{range $}} <tr> <td>{{.Type}}<br>{{.Frame.Fn}}<br>{{.Frame.File}}:{{.Frame.Line}}</td> - <td><a href="/userspan?type={{.Type}}&pc={{.Frame.PC}}">{{.Histogram.Count}}</a></td> - <td>{{.Histogram.ToHTML (.UserSpanURL)}}</td> + <td><a href="/userregion?type={{.Type}}&pc={{.Frame.PC}}">{{.Histogram.Count}}</a></td> + <td>{{.Histogram.ToHTML (.UserRegionURL)}}</td> </tr> {{end}} </table> @@ -1109,15 +1109,15 @@ func describeEvent(ev *trace.Event) string { return "goroutine stopped" case trace.EvUserLog: return formatUserLog(ev) - case trace.EvUserSpan: + case trace.EvUserRegion: if ev.Args[1] == 0 { duration := "unknown" if ev.Link != nil { duration = (time.Duration(ev.Link.Ts-ev.Ts) * time.Nanosecond).String() } - return fmt.Sprintf("span %s started (duration: %v)", ev.SArgs[0], duration) + return fmt.Sprintf("region %s started (duration: %v)", ev.SArgs[0], duration) } - return fmt.Sprintf("span %s ended", ev.SArgs[0]) + return fmt.Sprintf("region %s ended", ev.SArgs[0]) case trace.EvUserTaskCreate: return fmt.Sprintf("task %v (id %d, parent %d) created", ev.SArgs[0], ev.Args[0], ev.Args[1]) // TODO: add child task creation events into the parent task events @@ -1129,13 +1129,13 @@ func describeEvent(ev *trace.Event) string { func isUserAnnotationEvent(ev *trace.Event) bool { switch ev.Type { - case trace.EvUserLog, trace.EvUserSpan, trace.EvUserTaskCreate, trace.EvUserTaskEnd: + case trace.EvUserLog, trace.EvUserRegion, trace.EvUserTaskCreate, trace.EvUserTaskEnd: return true } return false } -var templUserSpanType = template.Must(template.New("").Funcs(template.FuncMap{ +var templUserRegionType = template.Must(template.New("").Funcs(template.FuncMap{ "prettyDuration": func(nsec int64) template.HTML { d := time.Duration(nsec) * time.Nanosecond return template.HTML(niceDuration(d)) @@ -1152,7 +1152,7 @@ var templUserSpanType = template.Must(template.New("").Funcs(template.FuncMap{ } return template.HTML(fmt.Sprintf("%.2f%%", float64(dividened)/float64(divisor)*100)) }, - "unknownTime": func(desc spanDesc) int64 { + "unknownTime": func(desc regionDesc) int64 { sum := desc.ExecTime + desc.IOTime + desc.BlockTime + desc.SyscallTime + desc.SchedWaitTime if sum < desc.TotalTime { return desc.TotalTime - sum diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go index 96b83734d7..5d2b226b35 100644 --- a/src/cmd/trace/annotations_test.go +++ b/src/cmd/trace/annotations_test.go @@ -47,9 +47,9 @@ func TestOverlappingDuration(t *testing.T) { // prog0 starts three goroutines. // -// goroutine 1: taskless span -// goroutine 2: starts task0, do work in task0.span0, starts task1 which ends immediately. -// goroutine 3: do work in task0.span1 and task0.span2, ends task0 +// goroutine 1: taskless region +// goroutine 2: starts task0, do work in task0.region0, starts task1 which ends immediately. +// goroutine 3: do work in task0.region1 and task0.region2, ends task0 func prog0() { ctx := context.Background() @@ -58,7 +58,7 @@ func prog0() { wg.Add(1) go func() { // goroutine 1 defer wg.Done() - trace.WithSpan(ctx, "taskless.span", func(ctx context.Context) { + trace.WithRegion(ctx, "taskless.region", func() { trace.Log(ctx, "key0", "val0") }) }() @@ -66,29 +66,29 @@ func prog0() { wg.Add(1) go func() { // goroutine 2 defer wg.Done() - ctx, taskDone := trace.NewContext(ctx, "task0") - trace.WithSpan(ctx, "task0.span0", func(ctx context.Context) { + ctx, task := trace.NewTask(ctx, "task0") + trace.WithRegion(ctx, "task0.region0", func() { wg.Add(1) go func() { // goroutine 3 defer wg.Done() - defer taskDone() - trace.WithSpan(ctx, "task0.span1", func(ctx context.Context) { - trace.WithSpan(ctx, "task0.span2", func(ctx context.Context) { + defer task.End() + trace.WithRegion(ctx, "task0.region1", func() { + trace.WithRegion(ctx, "task0.region2", func() { trace.Log(ctx, "key2", "val2") }) trace.Log(ctx, "key1", "val1") }) }() }) - ctx2, taskDone2 := trace.NewContext(ctx, "task1") + ctx2, task2 := trace.NewTask(ctx, "task1") trace.Log(ctx2, "key3", "val3") - taskDone2() + task2.End() }() wg.Wait() } func TestAnalyzeAnnotations(t *testing.T) { - // TODO: classify taskless spans + // TODO: classify taskless regions // Run prog0 and capture the execution trace. if err := traceProgram(t, prog0, "TestAnalyzeAnnotations"); err != nil { @@ -101,17 +101,17 @@ func TestAnalyzeAnnotations(t *testing.T) { } // For prog0, we expect - // - task with name = "task0", with three spans. - // - task with name = "task1", with no span. + // - task with name = "task0", with three regions. + // - task with name = "task1", with no region. wantTasks := map[string]struct { complete bool goroutines int - spans []string + regions []string }{ "task0": { complete: true, goroutines: 2, - spans: []string{"task0.span0", "", "task0.span1", "task0.span2"}, + regions: []string{"task0.region0", "", "task0.region1", "task0.region2"}, }, "task1": { complete: true, @@ -125,7 +125,7 @@ func TestAnalyzeAnnotations(t *testing.T) { t.Errorf("unexpected task: %s", task) continue } - if task.complete() != want.complete || len(task.goroutines) != want.goroutines || !reflect.DeepEqual(spanNames(task), want.spans) { + if task.complete() != want.complete || len(task.goroutines) != want.goroutines || !reflect.DeepEqual(regionNames(task), want.regions) { t.Errorf("got task %v; want %+v", task, want) } @@ -135,37 +135,37 @@ func TestAnalyzeAnnotations(t *testing.T) { t.Errorf("no more tasks; want %+v", wantTasks) } - wantSpans := []string{ - "", // an auto-created span for the goroutine 3 - "taskless.span", - "task0.span0", - "task0.span1", - "task0.span2", + wantRegions := []string{ + "", // an auto-created region for the goroutine 3 + "taskless.region", + "task0.region0", + "task0.region1", + "task0.region2", } - var gotSpans []string - for spanID := range res.spans { - gotSpans = append(gotSpans, spanID.Type) + var gotRegions []string + for regionID := range res.regions { + gotRegions = append(gotRegions, regionID.Type) } - sort.Strings(wantSpans) - sort.Strings(gotSpans) - if !reflect.DeepEqual(gotSpans, wantSpans) { - t.Errorf("got spans %q, want spans %q", gotSpans, wantSpans) + sort.Strings(wantRegions) + sort.Strings(gotRegions) + if !reflect.DeepEqual(gotRegions, wantRegions) { + t.Errorf("got regions %q, want regions %q", gotRegions, wantRegions) } } // prog1 creates a task hierarchy consisting of three tasks. func prog1() { ctx := context.Background() - ctx1, done1 := trace.NewContext(ctx, "task1") - defer done1() - trace.WithSpan(ctx1, "task1.span", func(ctx context.Context) { - ctx2, done2 := trace.NewContext(ctx, "task2") - defer done2() - trace.WithSpan(ctx2, "task2.span", func(ctx context.Context) { - ctx3, done3 := trace.NewContext(ctx, "task3") - defer done3() - trace.WithSpan(ctx3, "task3.span", func(ctx context.Context) { + ctx1, task1 := trace.NewTask(ctx, "task1") + defer task1.End() + trace.WithRegion(ctx1, "task1.region", func() { + ctx2, task2 := trace.NewTask(ctx1, "task2") + defer task2.End() + trace.WithRegion(ctx2, "task2.region", func() { + ctx3, task3 := trace.NewTask(ctx2, "task3") + defer task3.End() + trace.WithRegion(ctx3, "task3.region", func() { }) }) }) @@ -184,27 +184,27 @@ func TestAnalyzeAnnotationTaskTree(t *testing.T) { tasks := res.tasks // For prog0, we expect - // - task with name = "", with taskless.span in spans. - // - task with name = "task0", with three spans. + // - task with name = "", with taskless.region in regions. + // - task with name = "task0", with three regions. wantTasks := map[string]struct { parent string children []string - spans []string + regions []string }{ "task1": { parent: "", children: []string{"task2"}, - spans: []string{"task1.span"}, + regions: []string{"task1.region"}, }, "task2": { parent: "task1", children: []string{"task3"}, - spans: []string{"task2.span"}, + regions: []string{"task2.region"}, }, "task3": { parent: "task2", children: nil, - spans: []string{"task3.span"}, + regions: []string{"task3.region"}, }, } @@ -218,7 +218,7 @@ func TestAnalyzeAnnotationTaskTree(t *testing.T) { if parentName(task) != want.parent || !reflect.DeepEqual(childrenNames(task), want.children) || - !reflect.DeepEqual(spanNames(task), want.spans) { + !reflect.DeepEqual(regionNames(task), want.regions) { t.Errorf("got %v; want %+v", task, want) } } @@ -234,10 +234,10 @@ func TestAnalyzeAnnotationTaskTree(t *testing.T) { // prog2 returns the upper-bound gc time that overlaps with the first task. func prog2() (gcTime time.Duration) { ch := make(chan bool) - ctx1, done := trace.NewContext(context.Background(), "taskWithGC") - trace.WithSpan(ctx1, "taskWithGC.span1", func(ctx context.Context) { + ctx1, task := trace.NewTask(context.Background(), "taskWithGC") + trace.WithRegion(ctx1, "taskWithGC.region1", func() { go func() { - defer trace.StartSpan(ctx, "taskWithGC.span2")() + defer trace.StartRegion(ctx1, "taskWithGC.region2").End() <-ch }() s := time.Now() @@ -245,13 +245,13 @@ func prog2() (gcTime time.Duration) { gcTime = time.Since(s) close(ch) }) - done() + task.End() - ctx2, done2 := trace.NewContext(context.Background(), "taskWithoutGC") - trace.WithSpan(ctx2, "taskWithoutGC.span1", func(ctx context.Context) { + ctx2, task2 := trace.NewTask(context.Background(), "taskWithoutGC") + trace.WithRegion(ctx2, "taskWithoutGC.region1", func() { // do nothing. }) - done2() + task2.End() return gcTime } @@ -343,8 +343,8 @@ func traceProgram(t *testing.T, f func(), name string) error { return nil } -func spanNames(task *taskDesc) (ret []string) { - for _, s := range task.spans { +func regionNames(task *taskDesc) (ret []string) { + for _, s := range task.regions { ret = append(ret, s.Name) } return ret diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index 57608067f1..0c98b85c37 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -200,7 +200,7 @@ var templMain = template.Must(template.New("").Parse(` <a href="/syscall">Syscall blocking profile</a> (<a href="/syscall?raw=1" download="syscall.profile">⬇</a>)<br> <a href="/sched">Scheduler latency profile</a> (<a href="/sche?raw=1" download="sched.profile">⬇</a>)<br> <a href="/usertasks">User-defined tasks</a><br> -<a href="/userspans">User-defined spans</a><br> +<a href="/userregions">User-defined regions</a><br> </body> </html> `)) diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go index c0972f2b46..3389d2799b 100644 --- a/src/cmd/trace/pprof.go +++ b/src/cmd/trace/pprof.go @@ -42,10 +42,10 @@ func init() { http.HandleFunc("/syscall", serveSVGProfile(pprofByGoroutine(computePprofSyscall))) http.HandleFunc("/sched", serveSVGProfile(pprofByGoroutine(computePprofSched))) - http.HandleFunc("/spanio", serveSVGProfile(pprofBySpan(computePprofIO))) - http.HandleFunc("/spanblock", serveSVGProfile(pprofBySpan(computePprofBlock))) - http.HandleFunc("/spansyscall", serveSVGProfile(pprofBySpan(computePprofSyscall))) - http.HandleFunc("/spansched", serveSVGProfile(pprofBySpan(computePprofSched))) + http.HandleFunc("/regionio", serveSVGProfile(pprofByRegion(computePprofIO))) + http.HandleFunc("/regionblock", serveSVGProfile(pprofByRegion(computePprofBlock))) + http.HandleFunc("/regionsyscall", serveSVGProfile(pprofByRegion(computePprofSyscall))) + http.HandleFunc("/regionsched", serveSVGProfile(pprofByRegion(computePprofSched))) } // Record represents one entry in pprof-like profiles. @@ -75,13 +75,13 @@ func pprofByGoroutine(compute func(io.Writer, map[uint64][]interval, []*trace.Ev } } -func pprofBySpan(compute func(io.Writer, map[uint64][]interval, []*trace.Event) error) func(w io.Writer, r *http.Request) error { +func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event) error) func(w io.Writer, r *http.Request) error { return func(w io.Writer, r *http.Request) error { - filter, err := newSpanFilter(r) + filter, err := newRegionFilter(r) if err != nil { return err } - gToIntervals, err := pprofMatchingSpans(filter) + gToIntervals, err := pprofMatchingRegions(filter) if err != nil { return err } @@ -123,9 +123,9 @@ func pprofMatchingGoroutines(id string, events []*trace.Event) (map[uint64][]int return res, nil } -// pprofMatchingSpans returns the time intervals of matching spans +// pprofMatchingRegions returns the time intervals of matching regions // grouped by the goroutine id. If the filter is nil, returns nil without an error. -func pprofMatchingSpans(filter *spanFilter) (map[uint64][]interval, error) { +func pprofMatchingRegions(filter *regionFilter) (map[uint64][]interval, error) { res, err := analyzeAnnotations() if err != nil { return nil, err @@ -135,8 +135,8 @@ func pprofMatchingSpans(filter *spanFilter) (map[uint64][]interval, error) { } gToIntervals := make(map[uint64][]interval) - for id, spans := range res.spans { - for _, s := range spans { + for id, regions := range res.regions { + for _, s := range regions { if filter.match(id, s) { gToIntervals[s.G] = append(gToIntervals[s.G], interval{begin: s.firstTimestamp(), end: s.lastTimestamp()}) } @@ -144,10 +144,10 @@ func pprofMatchingSpans(filter *spanFilter) (map[uint64][]interval, error) { } for g, intervals := range gToIntervals { - // in order to remove nested spans and - // consider only the outermost spans, + // in order to remove nested regions and + // consider only the outermost regions, // first, we sort based on the start time - // and then scan through to select only the outermost spans. + // and then scan through to select only the outermost regions. sort.Slice(intervals, func(i, j int) bool { x := intervals[i].begin y := intervals[j].begin @@ -158,13 +158,13 @@ func pprofMatchingSpans(filter *spanFilter) (map[uint64][]interval, error) { }) var lastTimestamp int64 var n int - // select only the outermost spans. + // select only the outermost regions. for _, i := range intervals { if lastTimestamp <= i.begin { - intervals[n] = i // new non-overlapping span starts. + intervals[n] = i // new non-overlapping region starts. lastTimestamp = i.end n++ - } // otherwise, skip because this span overlaps with a previous span. + } // otherwise, skip because this region overlaps with a previous region. } gToIntervals[g] = intervals[:n] } diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go index e3bb40614d..19d6fa36a7 100644 --- a/src/cmd/trace/trace.go +++ b/src/cmd/trace/trace.go @@ -405,7 +405,7 @@ type traceContext struct { threadStats, prevThreadStats threadStats gstates, prevGstates [gStateCount]int64 - spanID int // last emitted span id. incremented in each emitSpan call. + regionID int // last emitted region id. incremented in each emitRegion call. } type heapStats struct { @@ -738,7 +738,7 @@ func generateTrace(params *traceParams, consumer traceConsumer) error { } } - // Display task and its spans if we are in task-oriented presentation mode. + // Display task and its regions if we are in task-oriented presentation mode. if ctx.mode&modeTaskOriented != 0 { taskRow := uint64(trace.GCP + 1) for _, task := range ctx.tasks { @@ -757,11 +757,11 @@ func generateTrace(params *traceParams, consumer traceConsumer) error { } ctx.emit(tEnd) - // If we are in goroutine-oriented mode, we draw spans. + // If we are in goroutine-oriented mode, we draw regions. // TODO(hyangah): add this for task/P-oriented mode (i.e., focustask view) too. if ctx.mode&modeGoroutineOriented != 0 { - for _, s := range task.spans { - ctx.emitSpan(s) + for _, s := range task.regions { + ctx.emitRegion(s) } } } @@ -859,23 +859,23 @@ func (ctx *traceContext) emitSlice(ev *trace.Event, name string) *ViewerEvent { return sl } -func (ctx *traceContext) emitSpan(s spanDesc) { +func (ctx *traceContext) emitRegion(s regionDesc) { if s.Name == "" { return } - ctx.spanID++ - spanID := ctx.spanID + ctx.regionID++ + regionID := ctx.regionID id := s.TaskID scopeID := fmt.Sprintf("%x", id) sl0 := &ViewerEvent{ - Category: "Span", + Category: "Region", Name: s.Name, Phase: "b", Time: float64(s.firstTimestamp()) / 1e3, Tid: s.G, - ID: uint64(spanID), + ID: uint64(regionID), Scope: scopeID, Cname: colorDeepMagenta, } @@ -885,12 +885,12 @@ func (ctx *traceContext) emitSpan(s spanDesc) { ctx.emit(sl0) sl1 := &ViewerEvent{ - Category: "Span", + Category: "Region", Name: s.Name, Phase: "e", Time: float64(s.lastTimestamp()) / 1e3, Tid: s.G, - ID: uint64(spanID), + ID: uint64(regionID), Scope: scopeID, Cname: colorDeepMagenta, } |
