func GoroutineStats(events []*Event) map[uint64]*GDesc {
gs := make(map[uint64]*GDesc)
var lastTs int64
- var gcStartTime int64
+ var gcStartTime int64 // gcStartTime == 0 indicates gc is inactive.
for _, ev := range events {
lastTs = ev.Ts
switch ev.Type {
g.ExecTime += ev.Ts - g.lastStartTime
g.TotalTime = ev.Ts - g.CreationTime
g.EndTime = ev.Ts
+ if gcStartTime != 0 {
+ if g.CreationTime < gcStartTime {
+ g.GCTime += ev.Ts - gcStartTime
+ } else {
+ // The goroutine's lifetime overlaps
+ // with a GC completely.
+ g.GCTime += ev.Ts - g.CreationTime
+ }
+ }
case EvGoBlockSend, EvGoBlockRecv, EvGoBlockSelect,
EvGoBlockSync, EvGoBlockCond:
g := gs[ev.G]
gcStartTime = ev.Ts
case EvGCDone:
for _, g := range gs {
- if g.EndTime == 0 {
+ if g.EndTime != 0 {
+ continue
+ }
+ if gcStartTime < g.CreationTime {
+ g.GCTime += ev.Ts - g.CreationTime
+ } else {
g.GCTime += ev.Ts - gcStartTime
}
}
+ gcStartTime = 0 // indicates gc is inactive.
}
}