1
0
mirror of https://github.com/golang/go synced 2024-11-18 02:54:47 -07:00

runtime: place lower limit on trigger ratio

This change makes it so that the GC pacer's trigger ratio can never fall
below 0.6. Upcoming changes to the allocator make it significantly more
scalable and thus much faster in certain cases, creating a large gap
between the performance of allocation and scanning. The consequence of
this is that the trigger ratio can drop very low (0.07 was observed) in
order to drop GC utilization. A low trigger ratio like this results in a
high amount of black allocations, which causes the live heap to appear
larger, and thus the heap, and RSS, grows to a much higher stable point.

This change alleviates the problem by placing a lower bound on the
trigger ratio. The expected (and confirmed) effect of this is that
utilization in certain scenarios will no longer converge to the expected
25%, and may go higher. As a result of this artificially high trigger
ratio, more time will also be spent doing GC assists compared to
dedicated mark workers, since the GC will be on for an artifically short
fraction of time (artificial with respect to the pacer). The biggest
concern of this change is that allocation latency will suffer as a
result, since there will now be more assists. But, upcoming changes to
the allocator reduce the latency enough to outweigh the expected
increase in latency from this change, without the blowup in RSS observed
from the changes to the allocator.

Updates #35112.

Change-Id: Idd7c94fa974d0de673304c4397e716e89bfbf09b
Reviewed-on: https://go-review.googlesource.com/c/go/+/200439
Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
Michael Knyszek 2019-10-10 16:58:43 -04:00
parent 54e6ba6724
commit 74af7fc603

View File

@ -769,11 +769,25 @@ func gcSetTriggerRatio(triggerRatio float64) {
goal = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100 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. // Set the trigger ratio, capped to reasonable bounds.
if triggerRatio < 0 { if triggerRatio < minTriggerRatio {
// This can happen if the mutator is allocating very // This can happen if the mutator is allocating very
// quickly or the GC is scanning very slowly. // quickly or the GC is scanning very slowly.
triggerRatio = 0 triggerRatio = minTriggerRatio
} else if gcpercent >= 0 { } else if gcpercent >= 0 {
// Ensure there's always a little margin so that the // Ensure there's always a little margin so that the
// mutator assist ratio isn't infinity. // mutator assist ratio isn't infinity.