8146436: Add -XX:-ShrinkHeapInSteps option (previously -XX:+UseAggressiveHeapShrink)
authorcjplummer
Mon, 21 Mar 2016 13:14:31 -0700
changeset 37166 8a5f1594e692
parent 37164 24bc914cc980
child 37167 53914a6631b5
8146436: Add -XX:-ShrinkHeapInSteps option (previously -XX:+UseAggressiveHeapShrink) Summary: Added ShrinkHeapInSteps option. Reviewed-by: jmasa, tbenson
hotspot/src/share/vm/gc/shared/cardGeneration.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java
hotspot/test/gc/arguments/TestShrinkHeapInSteps.java
--- a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Mon Mar 21 13:14:31 2016 -0700
@@ -254,19 +254,22 @@
     if (capacity_after_gc > maximum_desired_capacity) {
       // Capacity too large, compute shrinking size
       shrink_bytes = capacity_after_gc - maximum_desired_capacity;
-      // We don't want shrink all the way back to initSize if people call
-      // System.gc(), because some programs do that between "phases" and then
-      // we'd just have to grow the heap up again for the next phase.  So we
-      // damp the shrinking: 0% on the first call, 10% on the second call, 40%
-      // on the third call, and 100% by the fourth call.  But if we recompute
-      // size without shrinking, it goes back to 0%.
-      shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+      if (ShrinkHeapInSteps) {
+        // If ShrinkHeapInSteps is true (the default),
+        // we don't want to shrink all the way back to initSize if people call
+        // System.gc(), because some programs do that between "phases" and then
+        // we'd just have to grow the heap up again for the next phase.  So we
+        // damp the shrinking: 0% on the first call, 10% on the second call, 40%
+        // on the third call, and 100% by the fourth call.  But if we recompute
+        // size without shrinking, it goes back to 0%.
+        shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
+        if (current_shrink_factor == 0) {
+          _shrink_factor = 10;
+        } else {
+          _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
+        }
+      }
       assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
-      if (current_shrink_factor == 0) {
-        _shrink_factor = 10;
-      } else {
-        _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
-      }
       log_trace(gc, heap)("    shrinking:  initSize: %.1fK  maximum_desired_capacity: %.1fK",
                                initial_size() / (double) K, maximum_desired_capacity / (double) K);
       log_trace(gc, heap)("    shrink_bytes: %.1fK  current_shrink_factor: " SIZE_FORMAT "  new shrink factor: " SIZE_FORMAT "  _min_heap_delta_bytes: %.1fK",
--- a/hotspot/src/share/vm/runtime/globals.hpp	Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Mon Mar 21 13:14:31 2016 -0700
@@ -3272,6 +3272,11 @@
           range(0, 100)                                                     \
           constraint(MaxHeapFreeRatioConstraintFunc,AfterErgo)              \
                                                                             \
+  product(bool, ShrinkHeapInSteps, true,                                    \
+          "When disabled, informs the GC to shrink the java heap directly"  \
+          " to the target size at the next full GC rather than requiring"   \
+          " smaller steps during multiple full GCs.")                       \
+                                                                            \
   product(intx, SoftRefLRUPolicyMSPerMB, 1000,                              \
           "Number of milliseconds per MB of free space in the heap")        \
           range(0, max_intx)                                                \
--- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java	Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java	Mon Mar 21 13:14:31 2016 -0700
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
@@ -61,11 +61,11 @@
         negativeTest(-1, false, 50, false, options);
         negativeTest(50, true, -1, true, options);
 
-        positiveTest(10, false, 90, false, options);
-        positiveTest(10, true, 80, false, options);
-        positiveTest(20, false, 70, true, options);
-        positiveTest(25, true, 65, true, options);
-        positiveTest(40, false, 50, false, options);
+        positiveTest(10, false, 90, false, true, options);
+        positiveTest(10, true, 80, false, true, options);
+        positiveTest(20, false, 70, true, true, options);
+        positiveTest(25, true, 65, true, true, options);
+        positiveTest(40, false, 50, false, true, options);
     }
 
     /**
@@ -79,7 +79,7 @@
      * @param options additional options for JVM
      */
     public static void positiveTest(int minRatio, boolean useXminf,
-            int maxRatio, boolean useXmaxf,
+            int maxRatio, boolean useXmaxf, boolean shrinkHeapInSteps,
             LinkedList<String> options) throws Exception {
 
         LinkedList<String> vmOptions = new LinkedList<>(options);
@@ -90,9 +90,11 @@
                 "-Xms" + HEAP_SIZE,
                 "-XX:NewSize=" + NEW_SIZE,
                 "-XX:MaxNewSize=" + MAX_NEW_SIZE,
+                "-XX:" + (shrinkHeapInSteps ? '+' : '-') + "ShrinkHeapInSteps",
                 RatioVerifier.class.getName(),
                 Integer.toString(minRatio),
-                Integer.toString(maxRatio)
+                Integer.toString(maxRatio),
+                Boolean.toString(shrinkHeapInSteps)
         );
 
         ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
@@ -151,8 +153,8 @@
         public static LinkedList<Object> garbage = new LinkedList<>();
 
         public static void main(String args[]) throws Exception {
-            if (args.length != 2) {
-                throw new IllegalArgumentException("Expected 2 args: <minRatio> <maxRatio>");
+            if (args.length != 3) {
+                throw new IllegalArgumentException("Expected 3 args: <minRatio> <maxRatio> <shrinkHeapInSteps>");
             }
             if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld) {
                 System.out.println("Test is not applicable to parallel GC");
@@ -161,8 +163,10 @@
 
             double minRatio = Integer.valueOf(args[0]) / 100.0;
             double maxRatio = Integer.valueOf(args[1]) / 100.0;
+            boolean shrinkHeapInSteps = Boolean.valueOf(args[2]);
 
             long maxHeapSize = getMax();
+            int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1);
 
             // commit 0.5 of total heap size to have enough space
             // to both shink and expand
@@ -170,7 +174,7 @@
                 garbage.add(new byte[ARRAY_LENGTH]);
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that current heap free ratio lies between specified limits
             verifyRatio(minRatio, maxRatio);
 
@@ -185,7 +189,7 @@
                 memoryToFill -= CHUNK_SIZE;
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that after memory allocation heap free ratio is still conforming specified limits
             verifyRatio(minRatio, maxRatio);
             // Verify that heap was actually expanded
@@ -204,7 +208,7 @@
                 memoryToFree -= CHUNK_SIZE;
             }
 
-            forceGC();
+            forceGC(gcTries);
             // Verify that heap free ratio is still conforming specified limits
             verifyRatio(minRatio, maxRatio);
             // Verify that heap was actually shrinked
@@ -214,8 +218,8 @@
 
         }
 
-        public static void forceGC() {
-            for (int i = 0; i < GC_TRIES; i++) {
+        public static void forceGC(int gcTries) {
+            for (int i = 0; i < gcTries; i++) {
                 System.gc();
                 try {
                     Thread.sleep(10);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestShrinkHeapInSteps.java	Mon Mar 21 13:14:31 2016 -0700
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestShrinkHeapInSteps
+ * @key gc
+ * @summary Verify that -XX:-ShrinkHeapInSteps works properly.
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build TestMaxMinHeapFreeRatioFlags TestShrinkHeapInSteps
+ * @run driver/timeout=240 TestShrinkHeapInSteps
+ */
+
+import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Collections;
+import jdk.test.lib.Utils;
+
+public class TestShrinkHeapInSteps {
+    public static void main(String args[]) throws Exception {
+        LinkedList<String> options = new LinkedList<>(
+                Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*HeapFreeRatio","-XX:\\+ExplicitGCInvokesConcurrent"))
+        );
+
+        // Leverage the existing TestMaxMinHeapFreeRatioFlags test, but pass
+        // "false" for the shrinkHeapInSteps argument. This will cause it to
+        // run with -XX:-ShrinkHeapInSteps, and only do 1 full GC instead of 10.
+        TestMaxMinHeapFreeRatioFlags.positiveTest(10, false, 90, false, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(10, true, 80, false, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(20, false, 70, true, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(25, true, 65, true, false, options);
+        TestMaxMinHeapFreeRatioFlags.positiveTest(40, false, 50, false, false, options);
+    }
+}