1 /* 2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package gc.arguments; 25 26 /* 27 * @test TestSurvivorRatioFlag 28 * @key gc 29 * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value 30 * @requires vm.gc != "Z" & vm.gc != "Shenandoah" 31 * @library /test/lib 32 * @library / 33 * @modules java.base/jdk.internal.misc 34 * java.management 35 * @build sun.hotspot.WhiteBox 36 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 37 * @run driver gc.arguments.TestSurvivorRatioFlag 38 */ 39 40 import java.lang.management.MemoryUsage; 41 import java.util.Arrays; 42 import java.util.Collections; 43 import java.util.LinkedList; 44 import jdk.test.lib.process.OutputAnalyzer; 45 import jdk.test.lib.process.ProcessTools; 46 import jdk.test.lib.Utils; 47 import sun.hotspot.WhiteBox; 48 49 public class TestSurvivorRatioFlag { 50 51 public static final long M = 1024 * 1024; 52 public static final long HEAP_SIZE = 200 * M; 53 public static final long NEW_SIZE = 100 * M; 54 main(String args[])55 public static void main(String args[]) throws Exception { 56 LinkedList<String> options = new LinkedList<>( 57 Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*SurvivorRatio=[^ ]+")) 58 ); 59 60 testSurvivorRatio(3, options); 61 testSurvivorRatio(6, options); 62 testSurvivorRatio(10, options); 63 testSurvivorRatio(15, options); 64 testSurvivorRatio(20, options); 65 } 66 67 /** 68 * Verify that actual survivor ratio equal to specified. 69 * 70 * @param ratio survivor ratio that be verified 71 * @param options additional options to JVM 72 */ testSurvivorRatio(int ratio, LinkedList<String> options)73 public static void testSurvivorRatio(int ratio, LinkedList<String> options) throws Exception { 74 75 LinkedList<String> vmOptions = new LinkedList<>(options); 76 77 Collections.addAll(vmOptions, 78 "-Xbootclasspath/a:.", 79 "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", 80 "-XX:+UnlockDiagnosticVMOptions", 81 "-XX:+WhiteBoxAPI", 82 "-XX:GCLockerEdenExpansionPercent=0", 83 "-XX:MaxNewSize=" + NEW_SIZE, 84 "-XX:NewSize=" + NEW_SIZE, 85 "-Xmx" + HEAP_SIZE, 86 "-Xms" + HEAP_SIZE, 87 "-XX:SurvivorRatio=" + ratio, 88 SurvivorRatioVerifier.class.getName(), 89 Integer.toString(ratio) 90 ); 91 92 ProcessBuilder procBuilder = GCArguments.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()])); 93 OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); 94 analyzer.shouldHaveExitValue(0); 95 } 96 97 /** 98 * Class that verifies survivor ratio. 99 */ 100 public static class SurvivorRatioVerifier { 101 102 static WhiteBox wb = WhiteBox.getWhiteBox(); 103 104 public static final int MAX_ITERATIONS = 10; 105 public static final int ARRAY_LENGTH = 10000; 106 public static final int CHUNK_SIZE = 10000; 107 main(String args[])108 public static void main(String args[]) throws Exception { 109 if (args.length != 1) { 110 throw new IllegalArgumentException("Expected 1 arg: <ratio>"); 111 } 112 final int ratio = Integer.valueOf(args[0]); 113 114 AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifySurvivorRatio(ratio))); 115 allocator.allocateMemoryAndVerify(); 116 } 117 118 /** 119 * Verify that actual survivor ratio is equal to expected. 120 * Depending on selected young GC we verify that: 121 * - for DefNew and ParNew: eden_size / survivor_size is close to expectedRatio; 122 * - for PSNew: survivor_size equal to young_gen_size / expectedRatio; 123 * - for G1: survivor_regions <= young_list_length / expectedRatio. 124 */ verifySurvivorRatio(int expectedRatio)125 public static Void verifySurvivorRatio(int expectedRatio) { 126 GCTypes.YoungGCType type = GCTypes.YoungGCType.getYoungGCType(); 127 switch (type) { 128 case DefNew: 129 verifyDefNewSurvivorRatio(expectedRatio); 130 break; 131 case PSNew: 132 verifyPSSurvivorRatio(expectedRatio); 133 break; 134 case G1: 135 verifyG1SurvivorRatio(expectedRatio); 136 break; 137 default: 138 throw new RuntimeException("Unexpected young GC type"); 139 } 140 return null; 141 } 142 verifyDefNewSurvivorRatio(int expectedRatio)143 private static void verifyDefNewSurvivorRatio(int expectedRatio) { 144 MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage(); 145 MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage(); 146 147 int actualRatio = (int) (edenUsage.getCommitted() / survivorUsage.getCommitted()); 148 if (Math.abs(actualRatio - expectedRatio) > 1) { 149 throw new RuntimeException("Expected survivor ratio is: " + expectedRatio 150 + ", but observed ratio is: " + actualRatio); 151 } 152 } 153 verifyPSSurvivorRatio(int expectedRatio)154 private static void verifyPSSurvivorRatio(int expectedRatio) { 155 MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage(); 156 MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage(); 157 158 long youngGenSize = edenUsage.getMax() + 2 * survivorUsage.getMax(); 159 // for Paralle GC Min/InitialSurvivorRatio = SurvivorRatio + 2 160 long expectedSize = HeapRegionUsageTool.alignDown(youngGenSize / (expectedRatio + 2), 161 wb.psHeapGenerationAlignment()); 162 163 if (expectedSize != survivorUsage.getCommitted()) { 164 throw new RuntimeException("Expected survivor size is: " + expectedSize 165 + ", but observed size is: " + survivorUsage.getCommitted()); 166 } 167 } 168 verifyG1SurvivorRatio(int expectedRatio)169 private static void verifyG1SurvivorRatio(int expectedRatio) { 170 MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage(); 171 172 int regionSize = wb.g1RegionSize(); 173 int youngListLength = (int) Math.max(NEW_SIZE / regionSize, 1); 174 int expectedSurvivorRegions = (int) Math.ceil(youngListLength / (double) expectedRatio); 175 int observedSurvivorRegions = (int) (survivorUsage.getCommitted() / regionSize); 176 177 if (expectedSurvivorRegions < observedSurvivorRegions) { 178 throw new RuntimeException("Expected amount of G1 survivor regions is " 179 + expectedSurvivorRegions + ", but observed " 180 + observedSurvivorRegions); 181 } 182 } 183 } 184 } 185