Skip to content

Commit 081d27a

Browse files
committed
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 <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent e68c027 commit 081d27a

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

src/runtime/mgc.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ func gcBgMarkWorker() {
13831383
default:
13841384
throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")
13851385
case gcMarkWorkerDedicatedMode:
1386-
gcDrain(&pp.gcw, gcDrainUntilPreempt|gcDrainFlushBgCredit)
1386+
gcDrainMarkWorkerDedicated(&pp.gcw, true)
13871387
if gp.preempt {
13881388
// We were preempted. This is
13891389
// a useful signal to kick
@@ -1398,11 +1398,11 @@ func gcBgMarkWorker() {
13981398
}
13991399
// Go back to draining, this time
14001400
// without preemption.
1401-
gcDrain(&pp.gcw, gcDrainFlushBgCredit)
1401+
gcDrainMarkWorkerDedicated(&pp.gcw, false)
14021402
case gcMarkWorkerFractionalMode:
1403-
gcDrain(&pp.gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
1403+
gcDrainMarkWorkerFractional(&pp.gcw)
14041404
case gcMarkWorkerIdleMode:
1405-
gcDrain(&pp.gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
1405+
gcDrainMarkWorkerIdle(&pp.gcw)
14061406
}
14071407
casgstatus(gp, _Gwaiting, _Grunning)
14081408
})

src/runtime/mgcmark.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,28 @@ const (
10111011
gcDrainFractional
10121012
)
10131013

1014+
// gcDrainMarkWorkerIdle is a wrapper for gcDrain that exists to better account
1015+
// mark time in profiles.
1016+
func gcDrainMarkWorkerIdle(gcw *gcWork) {
1017+
gcDrain(gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
1018+
}
1019+
1020+
// gcDrainMarkWorkerDedicated is a wrapper for gcDrain that exists to better account
1021+
// mark time in profiles.
1022+
func gcDrainMarkWorkerDedicated(gcw *gcWork, untilPreempt bool) {
1023+
flags := gcDrainFlushBgCredit
1024+
if untilPreempt {
1025+
flags |= gcDrainUntilPreempt
1026+
}
1027+
gcDrain(gcw, flags)
1028+
}
1029+
1030+
// gcDrainMarkWorkerFractional is a wrapper for gcDrain that exists to better account
1031+
// mark time in profiles.
1032+
func gcDrainMarkWorkerFractional(gcw *gcWork) {
1033+
gcDrain(gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
1034+
}
1035+
10141036
// gcDrain scans roots and objects in work buffers, blackening grey
10151037
// objects until it is unable to get more work. It may return before
10161038
// GC is done; it's the caller's responsibility to balance work from
@@ -1032,6 +1054,14 @@ const (
10321054
//
10331055
// gcDrain will always return if there is a pending STW.
10341056
//
1057+
// Disabling write barriers is necessary to ensure that after we've
1058+
// confirmed that we've drained gcw, that we don't accidentally end
1059+
// up flipping that condition by immediately adding work in the form
1060+
// of a write barrier buffer flush.
1061+
//
1062+
// Don't set nowritebarrierrec because it's safe for some callees to
1063+
// have write barriers enabled.
1064+
//
10351065
//go:nowritebarrier
10361066
func gcDrain(gcw *gcWork, flags gcDrainFlags) {
10371067
if !writeBarrier.needed {

0 commit comments

Comments
 (0)