Commit 22000f54 authored by Austin Clements's avatar Austin Clements

runtime: record swept and reclaimed bytes in sweep trace

This extends the GCSweepDone event with counts of swept and reclaimed
bytes. These are useful for understanding the duration and
effectiveness of sweep events.

Change-Id: I3c97a4f0f3aad3adbd188adb264859775f54e2df
Reviewed-on: https://go-review.googlesource.com/40811
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarHyang-Ah Hana Kim <hyangah@gmail.com>
parent 79c56add
...@@ -849,16 +849,21 @@ func argNum(raw rawEvent, ver int) int { ...@@ -849,16 +849,21 @@ func argNum(raw rawEvent, ver int) int {
if ver < 1007 { if ver < 1007 {
narg++ // there was an unused arg before 1.7 narg++ // there was an unused arg before 1.7
} }
return narg
}
narg++ // timestamp
if ver < 1007 {
narg++ // sequence
}
switch raw.typ {
case EvGCSweepDone:
if ver < 1009 {
narg -= 2 // 1.9 added two arguments
}
case EvGCStart, EvGoStart, EvGoUnblock: case EvGCStart, EvGoStart, EvGoUnblock:
if ver < 1007 { if ver < 1007 {
narg-- // 1.7 added an additional seq arg narg-- // 1.7 added an additional seq arg
} }
fallthrough
default:
narg++ // timestamp
if ver < 1007 {
narg++ // sequence
}
} }
return narg return narg
} }
...@@ -881,7 +886,7 @@ const ( ...@@ -881,7 +886,7 @@ const (
EvGCScanStart = 9 // GC mark termination start [timestamp] EvGCScanStart = 9 // GC mark termination start [timestamp]
EvGCScanDone = 10 // GC mark termination done [timestamp] EvGCScanDone = 10 // GC mark termination done [timestamp]
EvGCSweepStart = 11 // GC sweep start [timestamp, stack id] EvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
EvGCSweepDone = 12 // GC sweep done [timestamp] EvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed]
EvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id] EvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id]
EvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq] EvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq]
EvGoEnd = 15 // goroutine ends [timestamp] EvGoEnd = 15 // goroutine ends [timestamp]
...@@ -935,7 +940,7 @@ var EventDescriptions = [EvCount]struct { ...@@ -935,7 +940,7 @@ var EventDescriptions = [EvCount]struct {
EvGCScanStart: {"GCScanStart", 1005, false, []string{}}, EvGCScanStart: {"GCScanStart", 1005, false, []string{}},
EvGCScanDone: {"GCScanDone", 1005, false, []string{}}, EvGCScanDone: {"GCScanDone", 1005, false, []string{}},
EvGCSweepStart: {"GCSweepStart", 1005, true, []string{}}, EvGCSweepStart: {"GCSweepStart", 1005, true, []string{}},
EvGCSweepDone: {"GCSweepDone", 1005, false, []string{}}, EvGCSweepDone: {"GCSweepDone", 1005, false, []string{"swept", "reclaimed"}}, // before 1.9, format was {}
EvGoCreate: {"GoCreate", 1005, true, []string{"g", "stack"}}, EvGoCreate: {"GoCreate", 1005, true, []string{"g", "stack"}},
EvGoStart: {"GoStart", 1005, false, []string{"g", "seq"}}, // in 1.5 format it was {"g"} EvGoStart: {"GoStart", 1005, false, []string{"g", "seq"}}, // in 1.5 format it was {"g"}
EvGoEnd: {"GoEnd", 1005, false, []string{}}, EvGoEnd: {"GoEnd", 1005, false, []string{}},
......
...@@ -190,7 +190,7 @@ func (s *mspan) sweep(preserve bool) bool { ...@@ -190,7 +190,7 @@ func (s *mspan) sweep(preserve bool) bool {
} }
if trace.enabled { if trace.enabled {
traceGCSweepSpan() traceGCSweepSpan(s.npages * _PageSize)
} }
atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages)) atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
...@@ -301,6 +301,9 @@ func (s *mspan) sweep(preserve bool) bool { ...@@ -301,6 +301,9 @@ func (s *mspan) sweep(preserve bool) bool {
s.allocCount = nalloc s.allocCount = nalloc
wasempty := s.nextFreeIndex() == s.nelems wasempty := s.nextFreeIndex() == s.nelems
s.freeindex = 0 // reset allocation index to start of span. s.freeindex = 0 // reset allocation index to start of span.
if trace.enabled {
getg().m.p.ptr().traceReclaimed += uintptr(nfreed) * s.elemsize
}
// gcmarkBits becomes the allocBits. // gcmarkBits becomes the allocBits.
// get a fresh cleared gcmarkBits in preparation for next GC // get a fresh cleared gcmarkBits in preparation for next GC
......
...@@ -490,10 +490,13 @@ type p struct { ...@@ -490,10 +490,13 @@ type p struct {
tracebuf traceBufPtr tracebuf traceBufPtr
// traceSweep indicates the next traceGCSweepSpan should emit // traceSweep indicates the sweep events should be traced.
// a sweep start event. This is used to defer the sweep start // This is used to defer the sweep start event until a span
// event until a span has actually been swept. // has actually been swept.
traceSweep bool traceSweep bool
// traceSwept and traceReclaimed track the number of bytes
// swept and reclaimed by sweeping in the current sweep loop.
traceSwept, traceReclaimed uintptr
palloc persistentAlloc // per-P to avoid mutex palloc persistentAlloc // per-P to avoid mutex
......
...@@ -31,7 +31,7 @@ const ( ...@@ -31,7 +31,7 @@ const (
traceEvGCScanStart = 9 // GC mark termination start [timestamp] traceEvGCScanStart = 9 // GC mark termination start [timestamp]
traceEvGCScanDone = 10 // GC mark termination done [timestamp] traceEvGCScanDone = 10 // GC mark termination done [timestamp]
traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id] traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
traceEvGCSweepDone = 12 // GC sweep done [timestamp] traceEvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed]
traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id] traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id]
traceEvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq] traceEvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq]
traceEvGoEnd = 15 // goroutine ends [timestamp] traceEvGoEnd = 15 // goroutine ends [timestamp]
...@@ -944,25 +944,30 @@ func traceGCSweepStart() { ...@@ -944,25 +944,30 @@ func traceGCSweepStart() {
if _p_.traceSweep { if _p_.traceSweep {
throw("double traceGCSweepStart") throw("double traceGCSweepStart")
} }
_p_.traceSweep = true _p_.traceSweep, _p_.traceSwept, _p_.traceReclaimed = true, 0, 0
} }
// traceGCSweepSpan traces the sweep of a single page. // traceGCSweepSpan traces the sweep of a single page.
// //
// This may be called outside a traceGCSweepStart/traceGCSweepDone // This may be called outside a traceGCSweepStart/traceGCSweepDone
// pair; however, it will not emit any trace events in this case. // pair; however, it will not emit any trace events in this case.
func traceGCSweepSpan() { func traceGCSweepSpan(bytesSwept uintptr) {
_p_ := getg().m.p.ptr() _p_ := getg().m.p.ptr()
if _p_.traceSweep { if _p_.traceSweep {
traceEvent(traceEvGCSweepStart, 1) if _p_.traceSwept == 0 {
_p_.traceSweep = false traceEvent(traceEvGCSweepStart, 1)
}
_p_.traceSwept += bytesSwept
} }
} }
func traceGCSweepDone() { func traceGCSweepDone() {
_p_ := getg().m.p.ptr() _p_ := getg().m.p.ptr()
if !_p_.traceSweep { if !_p_.traceSweep {
traceEvent(traceEvGCSweepDone, -1) throw("missing traceGCSweepStart")
}
if _p_.traceSwept != 0 {
traceEvent(traceEvGCSweepDone, -1, uint64(_p_.traceSwept), uint64(_p_.traceReclaimed))
} }
_p_.traceSweep = false _p_.traceSweep = false
} }
......
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