Skip to content

Commit 510fd13

Browse files
committed
runtime: enable GC assists ASAP
Currently the GC coordinator enables GC assists at the same time it enables background mark workers, after the concurrent scan phase is done. However, this means a rapidly allocating mutator has the entire scan phase during which to allocate beyond the heap trigger and potentially beyond the heap goal with no back-pressure from assists. This prevents the feedback system that's supposed to keep the heap size under the heap goal from doing its job. Fix this by enabling mutator assists during the scan phase. This is safe because the write barrier is already enabled and globally acknowledged at this point. There's still a very small window between when the heap size reaches the heap trigger and when the GC coordinator is able to stop the world during which the mutator can allocate unabated. This allows *very* rapidly allocator mutators like TestTraceStress to still occasionally exceed the heap goal by a small amount (~20 MB at most for TestTraceStress). However, this seems like a corner case. Fixes #11677. Change-Id: I0f80d949ec82341cd31ca1604a626efb7295a819 Reviewed-on: https://go-review.googlesource.com/12674 Reviewed-by: Russ Cox <[email protected]>
1 parent f5e67e5 commit 510fd13

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

src/runtime/mgc.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,15 @@ func gc(mode int) {
956956
// boundaries where there are up-pointers.
957957
setGCPhase(_GCscan)
958958

959+
gcBgMarkPrepare() // Must happen before assist enable.
960+
961+
// At this point all Ps have enabled the write
962+
// barrier, thus maintaining the no white to
963+
// black invariant. Enable mutator assists to
964+
// put back-pressure on fast allocating
965+
// mutators.
966+
atomicstore(&gcBlackenEnabled, 1)
967+
959968
// Concurrent scan.
960969
startTheWorldWithSema()
961970
now = nanotime()
@@ -976,17 +985,13 @@ func gc(mode int) {
976985
forEachP(func(*p) {})
977986
})
978987
// Concurrent mark.
979-
gcBgMarkPrepare() // Must happen before assist enable.
980-
// At this point all Ps have enabled the mark phase
981-
// write barrier, thus maintaining the no white to
982-
// black invariant. Mutator assists and mark workers
983-
// can now be enabled to safely blacken grey objects.
984-
atomicstore(&gcBlackenEnabled, 1)
985988
if debug.gctrace > 0 {
986989
tMark = nanotime()
987990
}
988991

989-
// Wait for background mark completion.
992+
// Enable background mark workers and wait for
993+
// background mark completion.
994+
gcController.bgMarkStartTime = nanotime()
990995
work.bgMark1.clear()
991996
work.bgMark1.wait()
992997

@@ -1230,7 +1235,6 @@ func gcBgMarkPrepare() {
12301235
// Reset background mark completion points.
12311236
work.bgMark1.done = 1
12321237
work.bgMark2.done = 1
1233-
gcController.bgMarkStartTime = nanotime()
12341238
}
12351239

12361240
func gcBgMarkWorker(p *p) {

src/runtime/mgcmark.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ func gcscan_m() {
2929
// Prepare flag indicating that the scan has not been completed.
3030
local_allglen := gcResetGState()
3131

32-
work.nwait = 0
3332
work.ndone = 0
34-
work.nproc = 1
3533
useOneP := uint32(1) // For now do not do this in parallel.
3634
// ackgcphase is not needed since we are not scanning running goroutines.
3735
parforsetup(work.markfor, useOneP, uint32(_RootCount+local_allglen), false, markroot)

0 commit comments

Comments
 (0)