]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use only dedicated mark workers at reasonable GOMAXPROCS
authorAustin Clements <austin@google.com>
Wed, 4 Oct 2017 21:07:09 +0000 (17:07 -0400)
committerAustin Clements <austin@google.com>
Fri, 13 Oct 2017 20:52:55 +0000 (20:52 +0000)
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 <rlh@golang.org>
src/runtime/mgc.go

index 32383736ec12fe153897ab68b24fec6302a8216b..83eb14f772939cd5bac96579e244d25678988440 100644 (file)
@@ -453,11 +453,28 @@ func (c *gcControllerState) startCycle() {
                memstats.next_gc = memstats.heap_live + 1024*1024
        }
 
-       // Compute the background mark utilization goal and divide it among
-       // dedicated and fractional workers.
+       // Compute the background mark utilization goal. In general,
+       // this may not come out exactly. We round the number of
+       // dedicated workers so that the utilization is closest to
+       // 25%. For small GOMAXPROCS, this would introduce too much
+       // error, so we add fractional workers in that case.
        totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization
-       c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal)
-       c.fractionalUtilizationGoal = totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)
+       c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5)
+       utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1
+       const maxUtilError = 0.3
+       if utilError < -maxUtilError || utilError > maxUtilError {
+               // Rounding put us more than 30% off our goal. With
+               // gcBackgroundUtilization of 25%, this happens for
+               // GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional
+               // workers to compensate.
+               if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal {
+                       // Too many dedicated workers.
+                       c.dedicatedMarkWorkersNeeded--
+               }
+               c.fractionalUtilizationGoal = totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)
+       } else {
+               c.fractionalUtilizationGoal = 0
+       }
        if c.fractionalUtilizationGoal > 0 {
                c.fractionalMarkWorkersNeeded = 1
        } else {
@@ -863,7 +880,8 @@ const gcGoalUtilization = 0.25
 // gcBackgroundUtilization is the fixed CPU utilization for background
 // marking. It must be <= gcGoalUtilization. The difference between
 // gcGoalUtilization and gcBackgroundUtilization will be made up by
-// mark assists.
+// mark assists. The scheduler will aim to use within 50% of this
+// goal.
 const gcBackgroundUtilization = 0.25
 
 // gcCreditSlack is the amount of scan work credit that can can