aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2020-03-18 15:09:40 +0000
committerIan Lance Taylor <iant@golang.org>2020-03-27 17:26:31 +0000
commit9d7dad18db88a666c6437917e26d18a167492302 (patch)
treea830f5752625f3d4cd95cfd066b83fba6417745f
parent612ef03a232edcb43e2dff6943b2a8167647ba78 (diff)
downloadgo-9d7dad18db88a666c6437917e26d18a167492302.tar.gz
go-9d7dad18db88a666c6437917e26d18a167492302.zip
[release-branch.go1.14] runtime: ensure minTriggerRatio never exceeds maxTriggerRatio
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>
-rw-r--r--src/runtime/mgc.go48
1 files changed, 28 insertions, 20 deletions
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 604d7d09b4..d034986cf4 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -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