Skip to content

Commit 315c28b

Browse files
committed
runtime: use only dedicated mark workers at reasonable GOMAXPROCS
When GOMAXPROCS is not small, fractional workers don't add much to throughput, but they do add to the latency of individual goroutines. In this case, it makes sense to just use dedicated workers, even if we can't exactly hit the 25% CPU goal with dedicated workers. This implements this logic by computing the number of dedicated mark workers that will us closest to the 25% target. We only fall back to fractional workers if that would be more than 30% off of the target (less than 17.5% or more than 32.5%, which in practice happens for GOMAXPROCS <= 3 and GOMAXPROCS == 6). Updates #21698. Change-Id: I484063adeeaa1190200e4ef210193a20e635d552 Reviewed-on: https://go-review.googlesource.com/68571 Reviewed-by: Rick Hudson <[email protected]>
1 parent 2792348 commit 315c28b

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/runtime/mgc.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,28 @@ func (c *gcControllerState) startCycle() {
453453
memstats.next_gc = memstats.heap_live + 1024*1024
454454
}
455455

456-
// Compute the background mark utilization goal and divide it among
457-
// dedicated and fractional workers.
456+
// Compute the background mark utilization goal. In general,
457+
// this may not come out exactly. We round the number of
458+
// dedicated workers so that the utilization is closest to
459+
// 25%. For small GOMAXPROCS, this would introduce too much
460+
// error, so we add fractional workers in that case.
458461
totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization
459-
c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal)
460-
c.fractionalUtilizationGoal = totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)
462+
c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5)
463+
utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1
464+
const maxUtilError = 0.3
465+
if utilError < -maxUtilError || utilError > maxUtilError {
466+
// Rounding put us more than 30% off our goal. With
467+
// gcBackgroundUtilization of 25%, this happens for
468+
// GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional
469+
// workers to compensate.
470+
if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal {
471+
// Too many dedicated workers.
472+
c.dedicatedMarkWorkersNeeded--
473+
}
474+
c.fractionalUtilizationGoal = totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)
475+
} else {
476+
c.fractionalUtilizationGoal = 0
477+
}
461478
if c.fractionalUtilizationGoal > 0 {
462479
c.fractionalMarkWorkersNeeded = 1
463480
} else {
@@ -863,7 +880,8 @@ const gcGoalUtilization = 0.25
863880
// gcBackgroundUtilization is the fixed CPU utilization for background
864881
// marking. It must be <= gcGoalUtilization. The difference between
865882
// gcGoalUtilization and gcBackgroundUtilization will be made up by
866-
// mark assists.
883+
// mark assists. The scheduler will aim to use within 50% of this
884+
// goal.
867885
const gcBackgroundUtilization = 0.25
868886

869887
// gcCreditSlack is the amount of scan work credit that can can

0 commit comments

Comments
 (0)