aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/debug
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-04-06 15:17:18 -0400
committerAustin Clements <austin@google.com>2017-04-21 17:42:01 +0000
commitd9308cbb516fc581ff7c7f77781d51604be44da6 (patch)
treee32dc1555bc9b23e2dca8501f506491dac7795f4 /src/runtime/debug
parent1c4f3c5ea0267e8ebc990ee67c09efa01cb59746 (diff)
downloadgo-d9308cbb516fc581ff7c7f77781d51604be44da6.tar.gz
go-d9308cbb516fc581ff7c7f77781d51604be44da6.zip
runtime/debug: expand SetGCPercent test
The current SetGCPercent test is, shall we say, minimal. Expand it to check that the GC target is actually computed and updated correctly. For #19076. Change-Id: I6e9b2ee0ef369f22f72e43b58d89e9f1e1b73b1b Reviewed-on: https://go-review.googlesource.com/39834 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rick Hudson <rlh@golang.org>
Diffstat (limited to 'src/runtime/debug')
-rw-r--r--src/runtime/debug/garbage_test.go63
1 files changed, 61 insertions, 2 deletions
diff --git a/src/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go
index 04e954b1b1..37417aca2c 100644
--- a/src/runtime/debug/garbage_test.go
+++ b/src/runtime/debug/garbage_test.go
@@ -104,15 +104,74 @@ func TestFreeOSMemory(t *testing.T) {
}
}
+var (
+ setGCPercentBallast interface{}
+ setGCPercentSink interface{}
+)
+
func TestSetGCPercent(t *testing.T) {
// Test that the variable is being set and returned correctly.
- // Assume the percentage itself is implemented fine during GC,
- // which is harder to test.
old := SetGCPercent(123)
new := SetGCPercent(old)
if new != 123 {
t.Errorf("SetGCPercent(123); SetGCPercent(x) = %d, want 123", new)
}
+
+ // Test that the percentage is implemented correctly.
+ defer func() {
+ SetGCPercent(old)
+ setGCPercentBallast, setGCPercentSink = nil, nil
+ }()
+ SetGCPercent(100)
+ runtime.GC()
+ // Create 100 MB of live heap as a baseline.
+ const baseline = 100 << 20
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ setGCPercentBallast = make([]byte, baseline-ms.Alloc)
+ runtime.GC()
+ runtime.ReadMemStats(&ms)
+ if abs64(baseline-int64(ms.Alloc)) > 10<<20 {
+ t.Fatalf("failed to set up baseline live heap; got %d MB, want %d MB", ms.Alloc>>20, baseline>>20)
+ }
+ // NextGC should be ~200 MB.
+ const thresh = 10 << 20
+ if want := int64(2 * baseline); abs64(want-int64(ms.NextGC)) > thresh {
+ t.Errorf("NextGC = %d MB, want %d±%d MB", ms.NextGC>>20, want>>20, thresh>>20)
+ }
+ // Create some garbage, but not enough to trigger another GC.
+ for i := 0; i < int(1.2*baseline); i += 1 << 10 {
+ setGCPercentSink = make([]byte, 1<<10)
+ }
+ setGCPercentSink = nil
+ // Adjust GOGC to 50. NextGC should be ~150 MB.
+ SetGCPercent(50)
+ runtime.ReadMemStats(&ms)
+ if want := int64(1.5 * baseline); abs64(want-int64(ms.NextGC)) > thresh {
+ t.Errorf("NextGC = %d MB, want %d±%d MB", ms.NextGC>>20, want>>20, thresh>>20)
+ }
+
+ // Trigger a GC and get back to 100 MB live with GOGC=100.
+ SetGCPercent(100)
+ runtime.GC()
+ // Raise live to 120 MB.
+ setGCPercentSink = make([]byte, int(0.2*baseline))
+ // Lower GOGC to 10. This must force a GC.
+ runtime.ReadMemStats(&ms)
+ ngc1 := ms.NumGC
+ SetGCPercent(10)
+ runtime.ReadMemStats(&ms)
+ ngc2 := ms.NumGC
+ if ngc1 == ngc2 {
+ t.Errorf("expected GC to run but it did not")
+ }
+}
+
+func abs64(a int64) int64 {
+ if a < 0 {
+ return -a
+ }
+ return a
}
func TestSetMaxThreadsOvf(t *testing.T) {