]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/debug: expand SetGCPercent test
authorAustin Clements <austin@google.com>
Thu, 6 Apr 2017 19:17:18 +0000 (15:17 -0400)
committerAustin Clements <austin@google.com>
Fri, 21 Apr 2017 17:42:01 +0000 (17:42 +0000)
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>
src/runtime/debug/garbage_test.go

index 04e954b1b1ef24af6b1060ebe5d225e503c83ed8..37417aca2c16a908b9dd6d22bebfeeaf72e63e4f 100644 (file)
@@ -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) {