1
0
mirror of https://github.com/golang/go synced 2024-09-30 05:24:29 -06:00

cmd/go/internal/trace: add function to distinguish goroutines

trace.StartGoroutine will associate the trace information on the context
with a new chrome profiler thread id. The chrome profiler doesn't
expect multiple trace events to have the same thread id, so this
will allow us to display concurrent events on the trace.

Updates #38714

Change-Id: I888b0cce15a5a01db66366716fdd85bf86c832cd
Reviewed-on: https://go-review.googlesource.com/c/go/+/248319
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Michael Matloob 2020-06-17 17:40:35 -04:00
parent abfeec5eb0
commit 49003da6d4

View File

@ -34,20 +34,33 @@ func StartSpan(ctx context.Context, name string) (context.Context, *Span) {
if !ok { if !ok {
return ctx, nil return ctx, nil
} }
childSpan := &Span{t: tc.t, name: name, start: time.Now()} childSpan := &Span{t: tc.t, name: name, tid: tc.tid, start: time.Now()}
tc.t.writeEvent(&traceviewer.Event{ tc.t.writeEvent(&traceviewer.Event{
Name: childSpan.name, Name: childSpan.name,
Time: float64(childSpan.start.UnixNano()) / float64(time.Microsecond), Time: float64(childSpan.start.UnixNano()) / float64(time.Microsecond),
TID: childSpan.tid,
Phase: "B", Phase: "B",
}) })
ctx = context.WithValue(ctx, traceKey{}, traceContext{tc.t}) ctx = context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.tid})
return ctx, childSpan return ctx, childSpan
} }
// Goroutine associates the context with a new Thread ID. The Chrome trace viewer associates each
// trace event with a thread, and doesn't expect events with the same thread id to happen at the
// same time.
func Goroutine(ctx context.Context) context.Context {
tc, ok := getTraceContext(ctx)
if !ok {
return ctx
}
return context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.t.getNextTID()})
}
type Span struct { type Span struct {
t *tracer t *tracer
name string name string
tid uint64
start time.Time start time.Time
end time.Time end time.Time
} }
@ -60,12 +73,15 @@ func (s *Span) Done() {
s.t.writeEvent(&traceviewer.Event{ s.t.writeEvent(&traceviewer.Event{
Name: s.name, Name: s.name,
Time: float64(s.end.UnixNano()) / float64(time.Microsecond), Time: float64(s.end.UnixNano()) / float64(time.Microsecond),
TID: s.tid,
Phase: "E", Phase: "E",
}) })
} }
type tracer struct { type tracer struct {
file chan traceFile // 1-buffered file chan traceFile // 1-buffered
nextTID uint64
} }
func (t *tracer) writeEvent(ev *traceviewer.Event) error { func (t *tracer) writeEvent(ev *traceviewer.Event) error {
@ -103,12 +119,17 @@ func (t *tracer) Close() error {
return firstErr return firstErr
} }
func (t *tracer) getNextTID() uint64 {
return atomic.AddUint64(&t.nextTID, 1)
}
// traceKey is the context key for tracing information. It is unexported to prevent collisions with context keys defined in // traceKey is the context key for tracing information. It is unexported to prevent collisions with context keys defined in
// other packages. // other packages.
type traceKey struct{} type traceKey struct{}
type traceContext struct { type traceContext struct {
t *tracer t *tracer
tid uint64
} }
// Start starts a trace which writes to the given file. // Start starts a trace which writes to the given file.