]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.14] runtime: ensure minTriggerRatio never exceeds maxTriggerRatio
authorMichael Anthony Knyszek <mknyszek@google.com>
Wed, 18 Mar 2020 15:09:40 +0000 (15:09 +0000)
committerIan Lance Taylor <iant@golang.org>
Fri, 27 Mar 2020 17:26:31 +0000 (17:26 +0000)
Currently, the capping logic for the GC trigger ratio is such that if
gcpercent is low, we may end up setting the trigger ratio far too high,
breaking the promise of SetGCPercent and GOGC has a trade-off knob (we
won't start a GC early enough, and we will use more memory).

This change modifies the capping logic for the trigger ratio by scaling
the minTriggerRatio with gcpercent the same way we scale
maxTriggerRatio.

For #37927.
Fixes #37928.

Change-Id: I2a048c1808fb67186333d3d5a6bee328be2f35da
Reviewed-on: https://go-review.googlesource.com/c/go/+/223937
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
(cherry picked from commit d1ecfcc1e8baa0bb3a9fb504e8c14125a69139ba)
Reviewed-on: https://go-review.googlesource.com/c/go/+/225637
Reviewed-by: David Chase <drchase@google.com>
src/runtime/mgc.go

index 604d7d09b4831d2413a8a2053f49540e9e75b2de..d034986cf47b87c78877f1143c50273ae0c0d558 100644 (file)
@@ -769,32 +769,40 @@ func gcSetTriggerRatio(triggerRatio float64) {
                goal = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100
        }
 
-       // If we let triggerRatio go too low, then if the application
-       // is allocating very rapidly we might end up in a situation
-       // where we're allocating black during a nearly always-on GC.
-       // The result of this is a growing heap and ultimately an
-       // increase in RSS. By capping us at a point >0, we're essentially
-       // saying that we're OK using more CPU during the GC to prevent
-       // this growth in RSS.
-       //
-       // The current constant was chosen empirically: given a sufficiently
-       // fast/scalable allocator with 48 Ps that could drive the trigger ratio
-       // to <0.05, this constant causes applications to retain the same peak
-       // RSS compared to not having this allocator.
-       const minTriggerRatio = 0.6
-
        // Set the trigger ratio, capped to reasonable bounds.
-       if triggerRatio < minTriggerRatio {
-               // This can happen if the mutator is allocating very
-               // quickly or the GC is scanning very slowly.
-               triggerRatio = minTriggerRatio
-       } else if gcpercent >= 0 {
+       if gcpercent >= 0 {
+               scalingFactor := float64(gcpercent) / 100
                // Ensure there's always a little margin so that the
                // mutator assist ratio isn't infinity.
-               maxTriggerRatio := 0.95 * float64(gcpercent) / 100
+               maxTriggerRatio := 0.95 * scalingFactor
                if triggerRatio > maxTriggerRatio {
                        triggerRatio = maxTriggerRatio
                }
+
+               // If we let triggerRatio go too low, then if the application
+               // is allocating very rapidly we might end up in a situation
+               // where we're allocating black during a nearly always-on GC.
+               // The result of this is a growing heap and ultimately an
+               // increase in RSS. By capping us at a point >0, we're essentially
+               // saying that we're OK using more CPU during the GC to prevent
+               // this growth in RSS.
+               //
+               // The current constant was chosen empirically: given a sufficiently
+               // fast/scalable allocator with 48 Ps that could drive the trigger ratio
+               // to <0.05, this constant causes applications to retain the same peak
+               // RSS compared to not having this allocator.
+               minTriggerRatio := 0.6 * scalingFactor
+               if triggerRatio < minTriggerRatio {
+                       triggerRatio = minTriggerRatio
+               }
+       } else if triggerRatio < 0 {
+               // gcpercent < 0, so just make sure we're not getting a negative
+               // triggerRatio. This case isn't expected to happen in practice,
+               // and doesn't really matter because if gcpercent < 0 then we won't
+               // ever consume triggerRatio further on in this function, but let's
+               // just be defensive here; the triggerRatio being negative is almost
+               // certainly undesirable.
+               triggerRatio = 0
        }
        memstats.triggerRatio = triggerRatio