Skip to content

Commit

Permalink
runtime/debug: don't trigger a GC on SetGCPercent
Browse files Browse the repository at this point in the history
Currently SetGCPercent forces a GC in order to recompute GC pacing.
Since we can now recompute pacing on the fly using gcSetTriggerRatio,
change SetGCPercent (really runtime.setGCPercent) to go through
gcSetTriggerRatio and not trigger a GC.

Fixes #19076.

Change-Id: Ib30d7ab1bb3b55219535b9f238108f3d45a1b522
Reviewed-on: https://go-review.googlesource.com/39835
Run-TryBot: Austin Clements <[email protected]>
Reviewed-by: Rick Hudson <[email protected]>
  • Loading branch information
aclements committed Apr 21, 2017
1 parent d9308cb commit 227fff2
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 22 deletions.
6 changes: 1 addition & 5 deletions src/runtime/debug/garbage.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,7 @@ func ReadGCStats(stats *GCStats) {
// at startup, or 100 if the variable is not set.
// A negative percentage disables garbage collection.
func SetGCPercent(percent int) int {
old := setGCPercent(int32(percent))
if percent >= 0 {
runtime.GC()
}
return int(old)
return int(setGCPercent(int32(percent)))
}

// FreeOSMemory forces a garbage collection followed by an
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/debug/garbage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ func TestSetGCPercent(t *testing.T) {
runtime.ReadMemStats(&ms)
ngc1 := ms.NumGC
SetGCPercent(10)
// It may require an allocation to actually force the GC.
setGCPercentSink = make([]byte, 1<<20)
runtime.ReadMemStats(&ms)
ngc2 := ms.NumGC
if ngc1 == ngc2 {
Expand Down
31 changes: 14 additions & 17 deletions src/runtime/mgc.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,21 @@ func gcinit() {
throw("size of Workbuf is suboptimal")
}

_ = setGCPercent(readgogc())
// No sweep on the first cycle.
mheap_.sweepdone = 1

// Set a reasonable initial GC trigger.
memstats.triggerRatio = 7 / 8.0
memstats.gc_trigger = heapminimum
// Compute the goal heap size based on the trigger:
// trigger = marked * (1 + triggerRatio)
// marked = trigger / (1 + triggerRatio)
// goal = marked * (1 + GOGC/100)
// = trigger / (1 + triggerRatio) * (1 + GOGC/100)
memstats.next_gc = uint64(float64(memstats.gc_trigger) / (1 + memstats.triggerRatio) * (1 + float64(gcpercent)/100))
if gcpercent < 0 {
memstats.next_gc = ^uint64(0)
}

// Fake a heap_marked value so it looks like a trigger at
// heapminimum is the appropriate growth from heap_marked.
// This will go into computing the initial GC goal.
memstats.heap_marked = uint64(float64(heapminimum) / (1 + memstats.triggerRatio))

// Set gcpercent from the environment. This will also compute
// and set the GC trigger and goal.
_ = setGCPercent(readgogc())

work.startSema = 1
work.markDoneSema = 1
}
Expand Down Expand Up @@ -226,12 +227,8 @@ func setGCPercent(in int32) (out int32) {
}
gcpercent = in
heapminimum = defaultHeapMinimum * uint64(gcpercent) / 100
if memstats.triggerRatio > float64(gcpercent)/100 {
memstats.triggerRatio = float64(gcpercent) / 100
}
// This is either in gcinit or followed by a STW GC, both of
// which will reset other stats like memstats.gc_trigger and
// memstats.next_gc to appropriate values.
// Update pacing in response to gcpercent change.
gcSetTriggerRatio(memstats.triggerRatio)
unlock(&mheap_.lock)
return out
}
Expand Down

0 comments on commit 227fff2

Please sign in to comment.