hotspot/test/gc/arguments/TestSurvivorRatioFlag.java
changeset 32625 054d452e4e06
child 33730 30e064828045
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java	Tue Sep 01 21:38:07 2015 +0300
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2015, 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 TestSurvivorRatioFlag
+ * @key gc
+ * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build TestSurvivorRatioFlag
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestSurvivorRatioFlag
+ */
+
+import jdk.test.lib.AllocationHelper;
+import java.lang.management.MemoryUsage;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import jdk.test.lib.HeapRegionUsageTool;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+public class TestSurvivorRatioFlag {
+
+    public static final long M = 1024 * 1024;
+    public static final long HEAP_SIZE = 200 * M;
+    public static final long NEW_SIZE = 100 * M;
+
+    public static void main(String args[]) throws Exception {
+        LinkedList<String> options = new LinkedList<>(
+                Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*SurvivorRatio=[^ ]+"))
+        );
+
+        testSurvivorRatio(3, options);
+        testSurvivorRatio(6, options);
+        testSurvivorRatio(10, options);
+        testSurvivorRatio(15, options);
+        testSurvivorRatio(20, options);
+    }
+
+    /**
+     * Verify that actual survivor ratio equal to specified.
+     *
+     * @param ratio survivor ratio that be verified
+     * @param options additional options to JVM
+     */
+    public static void testSurvivorRatio(int ratio, LinkedList<String> options) throws Exception {
+
+        LinkedList<String> vmOptions = new LinkedList<>(options);
+
+        Collections.addAll(vmOptions,
+                "-Xbootclasspath/a:.",
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:+WhiteBoxAPI",
+                "-XX:GCLockerEdenExpansionPercent=0",
+                "-XX:MaxNewSize=" + NEW_SIZE,
+                "-XX:NewSize=" + NEW_SIZE,
+                "-Xmx" + HEAP_SIZE,
+                "-Xms" + HEAP_SIZE,
+                "-XX:SurvivorRatio=" + ratio,
+                SurvivorRatioVerifier.class.getName(),
+                Integer.toString(ratio)
+        );
+
+        ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+        OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+        analyzer.shouldHaveExitValue(0);
+    }
+
+    /**
+     * Class that verifies survivor ratio.
+     */
+    public static class SurvivorRatioVerifier {
+
+        static WhiteBox wb = WhiteBox.getWhiteBox();
+
+        public static final int MAX_ITERATIONS = 10;
+        public static final int ARRAY_LENGTH = 10000;
+        public static final int CHUNK_SIZE = 10000;
+
+        public static void main(String args[]) throws Exception {
+            if (args.length != 1) {
+                throw new IllegalArgumentException("Expected 1 arg: <ratio>");
+            }
+            final int ratio = Integer.valueOf(args[0]);
+
+            AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifySurvivorRatio(ratio)));
+            allocator.allocateMemoryAndVerify();
+        }
+
+        /**
+         * Verify that actual survivor ratio is equal to expected.
+         * Depending on selected young GC we verify that:
+         * - for DefNew and ParNew: eden_size / survivor_size is close to expectedRatio;
+         * - for PSNew:             survivor_size equal to young_gen_size / expectedRatio;
+         * - for G1:                survivor_regions <= young_list_length / expectedRatio.
+         */
+        public static Void verifySurvivorRatio(int expectedRatio) {
+            GCTypes.YoungGCType type = GCTypes.YoungGCType.getYoungGCType();
+            switch (type) {
+                case DefNew:
+                case ParNew:
+                    verifyDefNewSurvivorRatio(expectedRatio);
+                    break;
+                case PSNew:
+                    verifyPSSurvivorRatio(expectedRatio);
+                    break;
+                case G1:
+                    verifyG1SurvivorRatio(expectedRatio);
+                    break;
+                default:
+                    throw new RuntimeException("Unexpected young GC type");
+            }
+            return null;
+        }
+
+        private static void verifyDefNewSurvivorRatio(int expectedRatio) {
+            MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();
+            MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+            int actualRatio = (int) (edenUsage.getCommitted() / survivorUsage.getCommitted());
+            if (Math.abs(actualRatio - expectedRatio) > 1) {
+                throw new RuntimeException("Expected survivor ratio is: " + expectedRatio
+                        + ", but observed ratio is: " + actualRatio);
+            }
+        }
+
+        private static void verifyPSSurvivorRatio(int expectedRatio) {
+            MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();
+            MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+            long youngGenSize = edenUsage.getMax() + 2 * survivorUsage.getMax();
+            // for Paralle GC Min/InitialSurvivorRatio = SurvivorRatio + 2
+            long expectedSize = HeapRegionUsageTool.alignDown(youngGenSize / (expectedRatio + 2),
+                    wb.psHeapGenerationAlignment());
+
+            if (expectedSize != survivorUsage.getCommitted()) {
+                throw new RuntimeException("Expected survivor size is: " + expectedSize
+                        + ", but observed size is: " + survivorUsage.getCommitted());
+            }
+        }
+
+        private static void verifyG1SurvivorRatio(int expectedRatio) {
+            MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+            int regionSize = wb.g1RegionSize();
+            int youngListLength = (int) Math.max(NEW_SIZE / regionSize, 1);
+            int expectedSurvivorRegions = (int) Math.ceil(youngListLength / (double) expectedRatio);
+            int observedSurvivorRegions = (int) (survivorUsage.getCommitted() / regionSize);
+
+            if (expectedSurvivorRegions < observedSurvivorRegions) {
+                throw new RuntimeException("Expected amount of G1 survivor regions is "
+                        + expectedSurvivorRegions + ", but observed "
+                        + observedSurvivorRegions);
+            }
+        }
+    }
+}