mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime,cmd/trace: trace GC STW events
Right now we only kind of sort of trace GC STW events. We emit events around mark termination, but those start well after stopping the world and end before starting it again, and we don't emit any events for sweep termination. Fix this by generalizing EvGCScanStart/EvGCScanDone. These were already re-purposed to indicate mark termination (despite the names). This commit renames them to EvGCSTWStart/EvGCSTWDone, adds an argument to indicate the STW reason, and shuffles the runtime to generate them right before stopping the world and right after starting the world, respectively. These events will make it possible to generate precise minimum mutator utilization (MMU) graphs and could be useful in detecting non-preemptible goroutines (e.g., #20792). Change-Id: If95783f370781d8ef66addd94886028103a7c26f Reviewed-on: https://go-review.googlesource.com/55411 Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
4a5c37793c
commit
b0392159f6
8 changed files with 71 additions and 48 deletions
|
|
@ -31,7 +31,7 @@ type Event struct {
|
|||
SArgs []string // event-type-specific string args
|
||||
// linked event (can be nil), depends on event type:
|
||||
// for GCStart: the GCStop
|
||||
// for GCScanStart: the GCScanDone
|
||||
// for GCSTWStart: the GCSTWDone
|
||||
// for GCSweepStart: the GCSweepDone
|
||||
// for GoCreate: first GoStart of the created goroutine
|
||||
// for GoStart/GoStartLabel: the associated GoEnd, GoBlock or other blocking event
|
||||
|
|
@ -128,7 +128,7 @@ func readTrace(r io.Reader) (ver int, events []rawEvent, strings map[uint64]stri
|
|||
return
|
||||
}
|
||||
switch ver {
|
||||
case 1005, 1007, 1008, 1009:
|
||||
case 1005, 1007, 1008, 1009, 1010:
|
||||
// Note: When adding a new version, add canned traces
|
||||
// from the old version to the test suite using mkcanned.bash.
|
||||
break
|
||||
|
|
@ -373,7 +373,18 @@ func parseEvents(ver int, rawEvents []rawEvent, strings map[uint64]string) (even
|
|||
if raw.typ == EvGoStartLabel {
|
||||
e.SArgs = []string{strings[e.Args[2]]}
|
||||
}
|
||||
case EvGCStart, EvGCDone, EvGCScanStart, EvGCScanDone:
|
||||
case EvGCSTWStart:
|
||||
e.G = 0
|
||||
switch e.Args[0] {
|
||||
case 0:
|
||||
e.SArgs = []string{"mark termination"}
|
||||
case 1:
|
||||
e.SArgs = []string{"sweep termination"}
|
||||
default:
|
||||
err = fmt.Errorf("unknown STW kind %d", e.Args[0])
|
||||
return
|
||||
}
|
||||
case EvGCStart, EvGCDone, EvGCSTWDone:
|
||||
e.G = 0
|
||||
case EvGoEnd, EvGoStop, EvGoSched, EvGoPreempt,
|
||||
EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv,
|
||||
|
|
@ -511,14 +522,14 @@ func postProcessTrace(ver int, events []*Event) error {
|
|||
type pdesc struct {
|
||||
running bool
|
||||
g uint64
|
||||
evScan *Event
|
||||
evSTW *Event
|
||||
evSweep *Event
|
||||
}
|
||||
|
||||
gs := make(map[uint64]gdesc)
|
||||
ps := make(map[int]pdesc)
|
||||
gs[0] = gdesc{state: gRunning}
|
||||
var evGC *Event
|
||||
var evGC, evSTW *Event
|
||||
|
||||
checkRunning := func(p pdesc, g gdesc, ev *Event, allowG0 bool) error {
|
||||
name := EventDescriptions[ev.Type].Name
|
||||
|
|
@ -565,17 +576,27 @@ func postProcessTrace(ver int, events []*Event) error {
|
|||
}
|
||||
evGC.Link = ev
|
||||
evGC = nil
|
||||
case EvGCScanStart:
|
||||
if p.evScan != nil {
|
||||
return fmt.Errorf("previous scanning is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts)
|
||||
case EvGCSTWStart:
|
||||
evp := &evSTW
|
||||
if ver < 1010 {
|
||||
// Before 1.10, EvGCSTWStart was per-P.
|
||||
evp = &p.evSTW
|
||||
}
|
||||
p.evScan = ev
|
||||
case EvGCScanDone:
|
||||
if p.evScan == nil {
|
||||
return fmt.Errorf("bogus scanning end (offset %v, time %v)", ev.Off, ev.Ts)
|
||||
if *evp != nil {
|
||||
return fmt.Errorf("previous STW is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts)
|
||||
}
|
||||
p.evScan.Link = ev
|
||||
p.evScan = nil
|
||||
*evp = ev
|
||||
case EvGCSTWDone:
|
||||
evp := &evSTW
|
||||
if ver < 1010 {
|
||||
// Before 1.10, EvGCSTWDone was per-P.
|
||||
evp = &p.evSTW
|
||||
}
|
||||
if *evp == nil {
|
||||
return fmt.Errorf("bogus STW end (offset %v, time %v)", ev.Off, ev.Ts)
|
||||
}
|
||||
(*evp).Link = ev
|
||||
*evp = nil
|
||||
case EvGCSweepStart:
|
||||
if p.evSweep != nil {
|
||||
return fmt.Errorf("previous sweeping is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts)
|
||||
|
|
@ -864,6 +885,10 @@ func argNum(raw rawEvent, ver int) int {
|
|||
if ver < 1007 {
|
||||
narg-- // 1.7 added an additional seq arg
|
||||
}
|
||||
case EvGCSTWStart:
|
||||
if ver < 1010 {
|
||||
narg-- // 1.10 added an argument
|
||||
}
|
||||
}
|
||||
return narg
|
||||
}
|
||||
|
|
@ -883,8 +908,8 @@ const (
|
|||
EvProcStop = 6 // stop of P [timestamp]
|
||||
EvGCStart = 7 // GC start [timestamp, seq, stack id]
|
||||
EvGCDone = 8 // GC done [timestamp]
|
||||
EvGCScanStart = 9 // GC mark termination start [timestamp]
|
||||
EvGCScanDone = 10 // GC mark termination done [timestamp]
|
||||
EvGCSTWStart = 9 // GC mark termination start [timestamp, kind]
|
||||
EvGCSTWDone = 10 // GC mark termination done [timestamp]
|
||||
EvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
|
||||
EvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed]
|
||||
EvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id]
|
||||
|
|
@ -937,8 +962,8 @@ var EventDescriptions = [EvCount]struct {
|
|||
EvProcStop: {"ProcStop", 1005, false, []string{}},
|
||||
EvGCStart: {"GCStart", 1005, true, []string{"seq"}}, // in 1.5 format it was {}
|
||||
EvGCDone: {"GCDone", 1005, false, []string{}},
|
||||
EvGCScanStart: {"GCScanStart", 1005, false, []string{}},
|
||||
EvGCScanDone: {"GCScanDone", 1005, false, []string{}},
|
||||
EvGCSTWStart: {"GCSTWStart", 1005, false, []string{"kind"}}, // <= 1.9, args was {} (implicitly {0})
|
||||
EvGCSTWDone: {"GCSTWDone", 1005, false, []string{}},
|
||||
EvGCSweepStart: {"GCSweepStart", 1005, true, []string{}},
|
||||
EvGCSweepDone: {"GCSweepDone", 1005, false, []string{"swept", "reclaimed"}}, // before 1.9, format was {}
|
||||
EvGoCreate: {"GoCreate", 1005, true, []string{"g", "stack"}},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue