aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/trace
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2016-10-08 18:38:35 -0400
committerAustin Clements <austin@google.com>2016-10-28 14:29:47 +0000
commit6da83c6fc006019f6fe0503099d165e19f465b1b (patch)
tree155fe589bc74911e73cd403ca40a9254af2feb81 /src/cmd/trace
parent640e9169155ea96a6f1156663269dba5babf0632 (diff)
downloadgo-6da83c6fc006019f6fe0503099d165e19f465b1b.tar.xz
runtime, cmd/trace: track goroutines blocked on GC assists
Currently when a goroutine blocks on a GC assist, it emits a generic EvGoBlock event. Since assist blocking events and, in particular, the length of the blocked assist queue, are important for diagnosing GC behavior, this commit adds a new EvGoBlockGC event for blocking on a GC assist. The trace viewer uses this event to report a "waiting on GC" count in the "Goroutines" row. This makes sense because, unlike other blocked goroutines, these goroutines do have work to do, so being blocked on a GC assist is quite similar to being in the "runnable" state, which we also report in the trace viewer. Change-Id: Ic21a326992606b121ea3d3d00110d8d1fdc7a5ef Reviewed-on: https://go-review.googlesource.com/30704 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Diffstat (limited to 'src/cmd/trace')
-rw-r--r--src/cmd/trace/pprof.go2
-rw-r--r--src/cmd/trace/trace.go14
2 files changed, 12 insertions, 4 deletions
diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go
index 636d23dc06..3bae15c608 100644
--- a/src/cmd/trace/pprof.go
+++ b/src/cmd/trace/pprof.go
@@ -62,7 +62,7 @@ func pprofBlock(w io.Writer) error {
for _, ev := range events {
switch ev.Type {
case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect,
- trace.EvGoBlockSync, trace.EvGoBlockCond:
+ trace.EvGoBlockSync, trace.EvGoBlockCond, trace.EvGoBlockGC:
default:
continue
}
diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go
index 37c14a286f..f92852f2a0 100644
--- a/src/cmd/trace/trace.go
+++ b/src/cmd/trace/trace.go
@@ -274,6 +274,7 @@ const (
gRunnable
gRunning
gWaiting
+ gWaitingGC
gStateCount
)
@@ -333,6 +334,10 @@ func generateTrace(params *traceParams) (ViewerData, error) {
// error in setGStateErr and check it after every event.
var setGStateErr error
setGState := func(ev *trace.Event, g uint64, oldState, newState gState) {
+ if oldState == gWaiting && gstates[g] == gWaitingGC {
+ // For checking, gWaiting counts as any gWaiting*.
+ oldState = gstates[g]
+ }
if gstates[g] != oldState && setGStateErr == nil {
setGStateErr = fmt.Errorf("expected G %d to be in state %d, but got state %d", g, oldState, newState)
}
@@ -428,6 +433,8 @@ func generateTrace(params *traceParams) (ViewerData, error) {
trace.EvGoSleep, trace.EvGoBlock, trace.EvGoBlockSend, trace.EvGoBlockRecv,
trace.EvGoBlockSelect, trace.EvGoBlockSync, trace.EvGoBlockCond, trace.EvGoBlockNet:
setGState(ev, ev.G, gRunning, gWaiting)
+ case trace.EvGoBlockGC:
+ setGState(ev, ev.G, gRunning, gWaitingGC)
case trace.EvGoWaiting:
setGState(ev, ev.G, gRunnable, gWaiting)
case trace.EvGoInSyscall:
@@ -536,15 +543,16 @@ func (ctx *traceContext) emitHeapCounters(ev *trace.Event) {
}
type goroutineCountersArg struct {
- Running uint64
- Runnable uint64
+ Running uint64
+ Runnable uint64
+ GCWaiting uint64
}
func (ctx *traceContext) emitGoroutineCounters(ev *trace.Event) {
if ctx.gtrace {
return
}
- ctx.emit(&ViewerEvent{Name: "Goroutines", Phase: "C", Time: ctx.time(ev), Pid: 1, Arg: &goroutineCountersArg{ctx.gstates[gRunning], ctx.gstates[gRunnable]}})
+ ctx.emit(&ViewerEvent{Name: "Goroutines", Phase: "C", Time: ctx.time(ev), Pid: 1, Arg: &goroutineCountersArg{ctx.gstates[gRunning], ctx.gstates[gRunnable], ctx.gstates[gWaitingGC]}})
}
type threadCountersArg struct {