Skip to content

Commit 227fff2

Browse files
committed
runtime/debug: don't trigger a GC on SetGCPercent
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]>
1 parent d9308cb commit 227fff2

File tree

3 files changed

+17
-22
lines changed

3 files changed

+17
-22
lines changed

src/runtime/debug/garbage.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,7 @@ func ReadGCStats(stats *GCStats) {
8989
// at startup, or 100 if the variable is not set.
9090
// A negative percentage disables garbage collection.
9191
func SetGCPercent(percent int) int {
92-
old := setGCPercent(int32(percent))
93-
if percent >= 0 {
94-
runtime.GC()
95-
}
96-
return int(old)
92+
return int(setGCPercent(int32(percent)))
9793
}
9894

9995
// FreeOSMemory forces a garbage collection followed by an

src/runtime/debug/garbage_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ func TestSetGCPercent(t *testing.T) {
160160
runtime.ReadMemStats(&ms)
161161
ngc1 := ms.NumGC
162162
SetGCPercent(10)
163+
// It may require an allocation to actually force the GC.
164+
setGCPercentSink = make([]byte, 1<<20)
163165
runtime.ReadMemStats(&ms)
164166
ngc2 := ms.NumGC
165167
if ngc1 == ngc2 {

src/runtime/mgc.go

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,21 @@ func gcinit() {
178178
throw("size of Workbuf is suboptimal")
179179
}
180180

181-
_ = setGCPercent(readgogc())
181+
// No sweep on the first cycle.
182+
mheap_.sweepdone = 1
182183

183184
// Set a reasonable initial GC trigger.
184185
memstats.triggerRatio = 7 / 8.0
185-
memstats.gc_trigger = heapminimum
186-
// Compute the goal heap size based on the trigger:
187-
// trigger = marked * (1 + triggerRatio)
188-
// marked = trigger / (1 + triggerRatio)
189-
// goal = marked * (1 + GOGC/100)
190-
// = trigger / (1 + triggerRatio) * (1 + GOGC/100)
191-
memstats.next_gc = uint64(float64(memstats.gc_trigger) / (1 + memstats.triggerRatio) * (1 + float64(gcpercent)/100))
192-
if gcpercent < 0 {
193-
memstats.next_gc = ^uint64(0)
194-
}
186+
187+
// Fake a heap_marked value so it looks like a trigger at
188+
// heapminimum is the appropriate growth from heap_marked.
189+
// This will go into computing the initial GC goal.
190+
memstats.heap_marked = uint64(float64(heapminimum) / (1 + memstats.triggerRatio))
191+
192+
// Set gcpercent from the environment. This will also compute
193+
// and set the GC trigger and goal.
194+
_ = setGCPercent(readgogc())
195+
195196
work.startSema = 1
196197
work.markDoneSema = 1
197198
}
@@ -226,12 +227,8 @@ func setGCPercent(in int32) (out int32) {
226227
}
227228
gcpercent = in
228229
heapminimum = defaultHeapMinimum * uint64(gcpercent) / 100
229-
if memstats.triggerRatio > float64(gcpercent)/100 {
230-
memstats.triggerRatio = float64(gcpercent) / 100
231-
}
232-
// This is either in gcinit or followed by a STW GC, both of
233-
// which will reset other stats like memstats.gc_trigger and
234-
// memstats.next_gc to appropriate values.
230+
// Update pacing in response to gcpercent change.
231+
gcSetTriggerRatio(memstats.triggerRatio)
235232
unlock(&mheap_.lock)
236233
return out
237234
}

0 commit comments

Comments
 (0)