runtime: create wrappers for gcDrain to identify time in profiles

Currently it's impossible to identify in profiles where gcDrain-related
time is coming from. More specifically, what kind of worker. Create
trivial wrappers for each worker so that the difference shows up in
stack traces.

Also, clarify why gcDrain disables write barriers.

Change-Id: I966e3c0b1c583994e691f486bf0ed8cabb91dbbb
Reviewed-on: https://go-review.googlesource.com/c/go/+/521815
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Michael Anthony Knyszek 2023-08-21 22:29:11 +00:00 committed by Michael Knyszek
parent e68c027204
commit 081d27a2e5
2 changed files with 34 additions and 4 deletions

View File

@ -1383,7 +1383,7 @@ func gcBgMarkWorker() {
default:
throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")
case gcMarkWorkerDedicatedMode:
gcDrain(&pp.gcw, gcDrainUntilPreempt|gcDrainFlushBgCredit)
gcDrainMarkWorkerDedicated(&pp.gcw, true)
if gp.preempt {
// We were preempted. This is
// a useful signal to kick
@ -1398,11 +1398,11 @@ func gcBgMarkWorker() {
}
// Go back to draining, this time
// without preemption.
gcDrain(&pp.gcw, gcDrainFlushBgCredit)
gcDrainMarkWorkerDedicated(&pp.gcw, false)
case gcMarkWorkerFractionalMode:
gcDrain(&pp.gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
gcDrainMarkWorkerFractional(&pp.gcw)
case gcMarkWorkerIdleMode:
gcDrain(&pp.gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
gcDrainMarkWorkerIdle(&pp.gcw)
}
casgstatus(gp, _Gwaiting, _Grunning)
})

View File

@ -1011,6 +1011,28 @@ const (
gcDrainFractional
)
// gcDrainMarkWorkerIdle is a wrapper for gcDrain that exists to better account
// mark time in profiles.
func gcDrainMarkWorkerIdle(gcw *gcWork) {
gcDrain(gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
}
// gcDrainMarkWorkerDedicated is a wrapper for gcDrain that exists to better account
// mark time in profiles.
func gcDrainMarkWorkerDedicated(gcw *gcWork, untilPreempt bool) {
flags := gcDrainFlushBgCredit
if untilPreempt {
flags |= gcDrainUntilPreempt
}
gcDrain(gcw, flags)
}
// gcDrainMarkWorkerFractional is a wrapper for gcDrain that exists to better account
// mark time in profiles.
func gcDrainMarkWorkerFractional(gcw *gcWork) {
gcDrain(gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
}
// gcDrain scans roots and objects in work buffers, blackening grey
// objects until it is unable to get more work. It may return before
// GC is done; it's the caller's responsibility to balance work from
@ -1032,6 +1054,14 @@ const (
//
// gcDrain will always return if there is a pending STW.
//
// Disabling write barriers is necessary to ensure that after we've
// confirmed that we've drained gcw, that we don't accidentally end
// up flipping that condition by immediately adding work in the form
// of a write barrier buffer flush.
//
// Don't set nowritebarrierrec because it's safe for some callees to
// have write barriers enabled.
//
//go:nowritebarrier
func gcDrain(gcw *gcWork, flags gcDrainFlags) {
if !writeBarrier.needed {