/* * Copyright (c) 2015, 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 TestSurvivorRatioFlag * @key gc * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * @run driver TestSurvivorRatioFlag */ import java.lang.management.MemoryUsage; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.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 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 options) throws Exception { LinkedList vmOptions = new LinkedList<>(options); Collections.addAll(vmOptions, "-Xbootclasspath/a:.", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-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: "); } 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); } } } }