1
0
mirror of https://github.com/golang/go synced 2024-11-22 20:14:40 -07:00

runtime: move gcPercent and heapMinimum into gcControllerState

These variables are core to the pacer, and will be need to be non-global
for testing later.

Partially generated via

rf '
    ex . {
	gcPercent -> gcController.gcPercent
	heapMinimum -> gcController.heapMinimum
    }
'

The only exception to this generation is usage of these variables
in gcControllerState methods.

For #44167.

Change-Id: I8b620b3061114f3a3c4b65006f715fd977b180a8
Reviewed-on: https://go-review.googlesource.com/c/go/+/306600
Trust: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Michael Anthony Knyszek 2021-04-01 17:56:32 +00:00 committed by Michael Knyszek
parent 728e3dc6f9
commit 2d4ba2601b
2 changed files with 32 additions and 31 deletions

View File

@ -153,6 +153,7 @@ func gcinit() {
if unsafe.Sizeof(workbuf{}) != _WorkbufSize { if unsafe.Sizeof(workbuf{}) != _WorkbufSize {
throw("size of Workbuf is suboptimal") throw("size of Workbuf is suboptimal")
} }
gcController.heapMinimum = defaultHeapMinimum
// No sweep on the first cycle. // No sweep on the first cycle.
mheap_.sweepDrained = 1 mheap_.sweepDrained = 1
@ -163,7 +164,7 @@ func gcinit() {
// Fake a heapMarked value so it looks like a trigger at // Fake a heapMarked value so it looks like a trigger at
// heapMinimum is the appropriate growth from heapMarked. // heapMinimum is the appropriate growth from heapMarked.
// This will go into computing the initial GC goal. // This will go into computing the initial GC goal.
gcController.heapMarked = uint64(float64(heapMinimum) / (1 + gcController.triggerRatio)) gcController.heapMarked = uint64(float64(gcController.heapMinimum) / (1 + gcController.triggerRatio))
// Set gcPercent from the environment. This will also compute // Set gcPercent from the environment. This will also compute
// and set the GC trigger and goal. // and set the GC trigger and goal.
@ -557,7 +558,7 @@ func (t gcTrigger) test() bool {
// own write. // own write.
return gcController.heapLive >= gcController.trigger return gcController.heapLive >= gcController.trigger
case gcTriggerTime: case gcTriggerTime:
if gcPercent < 0 { if gcController.gcPercent < 0 {
return false return false
} }
lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime)) lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime))

View File

@ -49,25 +49,6 @@ const (
defaultHeapMinimum = 4 << 20 defaultHeapMinimum = 4 << 20
) )
var (
// heapMinimum is the minimum heap size at which to trigger GC.
// For small heaps, this overrides the usual GOGC*live set rule.
//
// When there is a very small live set but a lot of allocation, simply
// collecting when the heap reaches GOGC*live results in many GC
// cycles and high total per-GC overhead. This minimum amortizes this
// per-GC overhead while keeping the heap reasonably small.
//
// During initialization this is set to 4MB*GOGC/100. In the case of
// GOGC==0, this will set heapMinimum to 0, resulting in constant
// collection even when the heap size is small, which is useful for
// debugging.
heapMinimum uint64 = defaultHeapMinimum
// Initialized from $GOGC. GOGC=off means no GC.
gcPercent int32
)
func init() { func init() {
if offset := unsafe.Offsetof(gcController.heapLive); offset%8 != 0 { if offset := unsafe.Offsetof(gcController.heapLive); offset%8 != 0 {
println(offset) println(offset)
@ -91,6 +72,25 @@ func init() {
var gcController gcControllerState var gcController gcControllerState
type gcControllerState struct { type gcControllerState struct {
// Initialized from $GOGC. GOGC=off means no GC.
gcPercent int32
_ uint32 // padding so following 64-bit values are 8-byte aligned
// heapMinimum is the minimum heap size at which to trigger GC.
// For small heaps, this overrides the usual GOGC*live set rule.
//
// When there is a very small live set but a lot of allocation, simply
// collecting when the heap reaches GOGC*live results in many GC
// cycles and high total per-GC overhead. This minimum amortizes this
// per-GC overhead while keeping the heap reasonably small.
//
// During initialization this is set to 4MB*GOGC/100. In the case of
// GOGC==0, this will set heapMinimum to 0, resulting in constant
// collection even when the heap size is small, which is useful for
// debugging.
heapMinimum uint64
// triggerRatio is the heap growth ratio that triggers marking. // triggerRatio is the heap growth ratio that triggers marking.
// //
// E.g., if this is 0.6, then GC should start when the live // E.g., if this is 0.6, then GC should start when the live
@ -337,7 +337,7 @@ func (c *gcControllerState) startCycle() {
// is when assists are enabled and the necessary statistics are // is when assists are enabled and the necessary statistics are
// available). // available).
func (c *gcControllerState) revise() { func (c *gcControllerState) revise() {
gcPercent := gcPercent gcPercent := c.gcPercent
if gcPercent < 0 { if gcPercent < 0 {
// If GC is disabled but we're running a forced GC, // If GC is disabled but we're running a forced GC,
// act like GOGC is huge for the below calculations. // act like GOGC is huge for the below calculations.
@ -624,13 +624,13 @@ func (c *gcControllerState) commit(triggerRatio float64) {
// has grown by GOGC/100 over the heap marked by the last // has grown by GOGC/100 over the heap marked by the last
// cycle. // cycle.
goal := ^uint64(0) goal := ^uint64(0)
if gcPercent >= 0 { if c.gcPercent >= 0 {
goal = c.heapMarked + c.heapMarked*uint64(gcPercent)/100 goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent)/100
} }
// Set the trigger ratio, capped to reasonable bounds. // Set the trigger ratio, capped to reasonable bounds.
if gcPercent >= 0 { if c.gcPercent >= 0 {
scalingFactor := float64(gcPercent) / 100 scalingFactor := float64(c.gcPercent) / 100
// 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.
maxTriggerRatio := 0.95 * scalingFactor maxTriggerRatio := 0.95 * scalingFactor
@ -670,10 +670,10 @@ func (c *gcControllerState) commit(triggerRatio float64) {
// We trigger the next GC cycle when the allocated heap has // We trigger the next GC cycle when the allocated heap has
// grown by the trigger ratio over the marked heap size. // grown by the trigger ratio over the marked heap size.
trigger := ^uint64(0) trigger := ^uint64(0)
if gcPercent >= 0 { if c.gcPercent >= 0 {
trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio)) trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio))
// Don't trigger below the minimum heap size. // Don't trigger below the minimum heap size.
minTrigger := heapMinimum minTrigger := c.heapMinimum
if !isSweepDone() { if !isSweepDone() {
// Concurrent sweep happens in the heap growth // Concurrent sweep happens in the heap growth
// from gcController.heapLive to trigger, so ensure // from gcController.heapLive to trigger, so ensure
@ -774,12 +774,12 @@ func setGCPercent(in int32) (out int32) {
// Run on the system stack since we grab the heap lock. // Run on the system stack since we grab the heap lock.
systemstack(func() { systemstack(func() {
lock(&mheap_.lock) lock(&mheap_.lock)
out = gcPercent out = gcController.gcPercent
if in < 0 { if in < 0 {
in = -1 in = -1
} }
gcPercent = in gcController.gcPercent = in
heapMinimum = defaultHeapMinimum * uint64(gcPercent) / 100 gcController.heapMinimum = defaultHeapMinimum * uint64(gcController.gcPercent) / 100
// Update pacing in response to gcPercent change. // Update pacing in response to gcPercent change.
gcController.commit(gcController.triggerRatio) gcController.commit(gcController.triggerRatio)
unlock(&mheap_.lock) unlock(&mheap_.lock)