TestIHOPStatic.java revision 10746:d9d1edafdf2d
1/* 2 * Copyright (c) 2016, 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 /* 25 * @test TestIHOPStatic 26 * @bug 8148397 27 * @summary Test checks concurrent cycle initiation which depends on IHOP value. 28 * @requires vm.gc=="G1" | vm.gc=="null" 29 * @requires vm.opt.FlightRecorder != true 30 * @requires vm.opt.ExplicitGCInvokesConcurrent != true 31 * @library /testlibrary / 32 * @modules java.management 33 * @build gc.g1.ihop.TestIHOPStatic 34 * gc.g1.ihop.lib.IhopUtils 35 * @run driver/timeout=240 gc.g1.ihop.TestIHOPStatic 36 */ 37package gc.g1.ihop; 38 39import java.util.ArrayList; 40import java.util.Collections; 41import java.util.List; 42 43import jdk.test.lib.OutputAnalyzer; 44import jdk.test.lib.ProcessTools; 45import jdk.test.lib.Utils; 46 47import gc.g1.ihop.lib.IhopUtils; 48 49/** 50 * The test starts the AppIHOP multiple times varying setting of MaxHeapSize, 51 * IHOP and amount of memory to allocate. Then the test parses the GC log from 52 * the app to check that Concurrent Mark Cycle was initiated only if needed 53 * and at the right moment, defined by IHOP setting. 54 */ 55public class TestIHOPStatic { 56 57 final static long YOUNG_SIZE = 8 * 1024 * 1024; 58 59 private final static String[] COMMON_OPTIONS = { 60 "-XX:+UseG1GC", 61 "-XX:G1HeapRegionSize=1m", 62 "-XX:-G1UseAdaptiveIHOP", 63 "-XX:NewSize=" + YOUNG_SIZE, 64 "-XX:MaxNewSize=" + YOUNG_SIZE, 65 "-Xlog:gc+ihop+ergo=debug,gc*=debug" 66 }; 67 68 public static void main(String[] args) throws Throwable { 69 70 // Test case: 71 // IHOP value, heap occupancy, heap size, expectation of message 72 // Test cases for occupancy is greater than IHOP 73 runTest(30, 35, 64, true); 74 runTest(50, 55, 256, true); 75 runTest(60, 65, 64, true); 76 runTest(70, 75, 512, true); 77 78 // Test cases for big difference between occupancy and IHOP 79 runTest(30, 50, 256, true); 80 runTest(30, 70, 512, true); 81 runTest(50, 70, 256, true); 82 83 // Test cases for occupancy is less than IHOP 84 runTest(30, 25, 64, false); 85 runTest(50, 45, 256, false); 86 runTest(70, 65, 64, false); 87 runTest(70, 65, 512, false); 88 89 // Test cases for big difference between occupancy and IHOP 90 runTest(50, 30, 300, false); 91 runTest(70, 50, 160, false); 92 93 // Cases for 0 and 100 IHOP. 94 runTest(0, 50, 256, true); 95 runTest(0, 95, 512, true); 96 runTest(100, 20, 64, false); 97 runTest(100, 100, 512, false); 98 } 99 100 /** 101 * Runs the test case. 102 * 103 * @param ihop IHOP value 104 * @param pctToFill heap percentage to be filled 105 * @param heapSize heap size for test 106 * @param expectInitiationMessage 107 * true - concurrent cycle initiation message is expected 108 * false - message is not expected 109 * 110 * @throws Throwable 111 */ 112 private static void runTest(int ihop, long pctToFill, long heapSize, boolean expectInitiationMessage) throws Throwable { 113 System.out.println(""); 114 System.out.println("IHOP test:"); 115 System.out.println(" InitiatingHeapOccupancyPercent : " + ihop); 116 System.out.println(" Part of heap to fill (percentage) : " + pctToFill); 117 System.out.println(" MaxHeapSize : " + heapSize); 118 System.out.println(" Expect for concurrent cycle initiation message : " + expectInitiationMessage); 119 List<String> options = new ArrayList<>(); 120 Collections.addAll(options, Utils.getTestJavaOpts()); 121 Collections.addAll(options, 122 "-XX:InitiatingHeapOccupancyPercent=" + ihop, 123 "-Dmemory.fill=" + (heapSize * 1024 * 1024 * pctToFill / 100), 124 "-XX:MaxHeapSize=" + heapSize + "M", 125 "-XX:InitialHeapSize=" + heapSize + "M" 126 ); 127 Collections.addAll(options, COMMON_OPTIONS); 128 options.add(AppIHOP.class.getName()); 129 130 OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()])); 131 132 if (out.getExitValue() != 0) { 133 System.out.println(out.getOutput()); 134 throw new RuntimeException("IhopTest failed with exit code " + out.getExitValue()); 135 } 136 137 checkResult(out, expectInitiationMessage); 138 } 139 140 /** 141 * Checks execution results to ensure that concurrent cycle was initiated or 142 * was not. 143 * 144 * @param out 145 * @param expectInitiationMessage true - test expects for concurrent cycle initiation. 146 * false - test does not expect for concurrent cycle initiation 147 */ 148 private static void checkResult(OutputAnalyzer out, boolean expectInitiationMessage) { 149 // Find expected messages 150 List<String> logItems = IhopUtils.getErgoInitiationMessages(out); 151 152 // Concurrent cycle was not initiated but was expected. 153 if (logItems.isEmpty() && expectInitiationMessage) { 154 System.out.println(out.getOutput()); 155 throw new RuntimeException("Concurrent cycle was not initiated."); 156 } 157 IhopUtils.checkIhopLogValues(out); 158 } 159 160 static class AppIHOP { 161 162 /** 163 * Simple class which fills part of memory and initiates GC. 164 * To be executed in separate VM. 165 * Expect next VM properties to be set: 166 * memory.fill - amount of garbage to be created. 167 */ 168 private static final long MEMORY_TO_FILL = Integer.getInteger("memory.fill"); 169 private final static int CHUNK_SIZE = 10000; 170 171 public final static ArrayList<Object> STORAGE = new ArrayList<>(); 172 173 public static void main(String[] args) throws InterruptedException { 174 175 // Calculate part of heap to be filled to achieve expected occupancy. 176 System.out.println("Mem to fill:" + MEMORY_TO_FILL); 177 if (MEMORY_TO_FILL <= 0) { 178 throw new RuntimeException("Wrong memory size: " + MEMORY_TO_FILL); 179 } 180 try { 181 createGarbage(MEMORY_TO_FILL); 182 } catch (OutOfMemoryError oome) { 183 return; 184 } 185 // Concurrent cycle initiation should start at end of Young GC cycle. 186 // Will fill entire young gen with garbage to guarantee that Young GC was initiated. 187 try { 188 createGarbage(TestIHOPStatic.YOUNG_SIZE); 189 } catch (OutOfMemoryError oome) { 190 } 191 } 192 193 private static void createGarbage(long memToFill) { 194 for (long i = 0; i < memToFill / CHUNK_SIZE; i++) { 195 STORAGE.add(new byte[CHUNK_SIZE]); 196 } 197 } 198 } 199} 200