Commit eed309f5 authored by Austin Clements's avatar Austin Clements

cmd/trace: move process-wide GC events to their own row

Currently, the process-wide GC state is attributed to the P that
happened to perform the allocation that exceeded the GC trigger. This
is pretty arbitrary and makes it hard to see when GC is running since
the GC spans are intermingled with a lot of other trace noise.

The current display is particularly confusing because it creates three
sub-rows in the P row that can overlap each other. Usually a P has
just two sub-rows: one showing the current G and another showing that
G's activity. However, because GC is attributed to a proc, it winds up
as a third row that neither subsumes nor is subsumed by any other row.
This in turn screws up the trace's layout and results in overlapping
events.

Fix these problems by creating a new dedicated row like the existing
"Network" and "Timer" rows and displaying process-wide GC events in
this row. Mark termination and sweep events still appear in their
respective P rows because these are meaningfully attributed.

Change-Id: Ie1a1c6cf8c446e4b043f10f3968f91ff1b546d15
Reviewed-on: https://go-review.googlesource.com/30017Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
parent fa9b57bb
...@@ -429,6 +429,9 @@ func generateTrace(params *traceParams) ViewerData { ...@@ -429,6 +429,9 @@ func generateTrace(params *traceParams) ViewerData {
ctx.emit(&ViewerEvent{Name: "process_name", Phase: "M", Pid: 1, Arg: &NameArg{"STATS"}}) ctx.emit(&ViewerEvent{Name: "process_name", Phase: "M", Pid: 1, Arg: &NameArg{"STATS"}})
ctx.emit(&ViewerEvent{Name: "process_sort_index", Phase: "M", Pid: 1, Arg: &SortIndexArg{0}}) ctx.emit(&ViewerEvent{Name: "process_sort_index", Phase: "M", Pid: 1, Arg: &SortIndexArg{0}})
ctx.emit(&ViewerEvent{Name: "thread_name", Phase: "M", Pid: 0, Tid: trace.GCP, Arg: &NameArg{"GC"}})
ctx.emit(&ViewerEvent{Name: "thread_sort_index", Phase: "M", Pid: 0, Tid: trace.GCP, Arg: &SortIndexArg{-6}})
ctx.emit(&ViewerEvent{Name: "thread_name", Phase: "M", Pid: 0, Tid: trace.NetpollP, Arg: &NameArg{"Network"}}) ctx.emit(&ViewerEvent{Name: "thread_name", Phase: "M", Pid: 0, Tid: trace.NetpollP, Arg: &NameArg{"Network"}})
ctx.emit(&ViewerEvent{Name: "thread_sort_index", Phase: "M", Pid: 0, Tid: trace.NetpollP, Arg: &SortIndexArg{-5}}) ctx.emit(&ViewerEvent{Name: "thread_sort_index", Phase: "M", Pid: 0, Tid: trace.NetpollP, Arg: &SortIndexArg{-5}})
......
...@@ -56,6 +56,7 @@ const ( ...@@ -56,6 +56,7 @@ const (
TimerP // depicts timer unblocks TimerP // depicts timer unblocks
NetpollP // depicts network unblocks NetpollP // depicts network unblocks
SyscallP // depicts returns from syscalls SyscallP // depicts returns from syscalls
GCP // depicts GC state
) )
// Parse parses, post-processes and verifies the trace. // Parse parses, post-processes and verifies the trace.
...@@ -548,6 +549,8 @@ func postProcessTrace(ver int, events []*Event) error { ...@@ -548,6 +549,8 @@ func postProcessTrace(ver int, events []*Event) error {
return fmt.Errorf("previous GC is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts) return fmt.Errorf("previous GC is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts)
} }
evGC = ev evGC = ev
// Attribute this to the global GC state.
ev.P = GCP
case EvGCDone: case EvGCDone:
if evGC == nil { if evGC == nil {
return fmt.Errorf("bogus GC end (offset %v, time %v)", ev.Off, ev.Ts) return fmt.Errorf("bogus GC end (offset %v, time %v)", ev.Off, ev.Ts)
......
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