1 /* 2 * Copyright (c) 2015, 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 package gc.g1.humongousObjects; 26 27 import jdk.test.lib.Asserts; 28 import sun.hotspot.WhiteBox; 29 30 /** 31 * @test TestHumongousThreshold 32 * @summary Checks that objects larger than half a region are allocated as humongous 33 * @requires vm.gc=="G1" | vm.gc=="null" 34 * @library /testlibrary /../../test/lib 35 * @modules java.management 36 * @build sun.hotspot.WhiteBox 37 * gc.g1.humongousObjects.Helpers 38 * gc.g1.humongousObjects.TestHumongousThreshold 39 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 40 * sun.hotspot.WhiteBox$WhiteBoxPermission 41 * 42 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 43 * -XX:G1HeapRegionSize=1M 44 * gc.g1.humongousObjects.TestHumongousThreshold 45 * 46 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 47 * -XX:G1HeapRegionSize=2M 48 * gc.g1.humongousObjects.TestHumongousThreshold 49 * 50 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 51 * -XX:G1HeapRegionSize=4M 52 * gc.g1.humongousObjects.TestHumongousThreshold 53 * 54 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 55 * -XX:G1HeapRegionSize=8M 56 * gc.g1.humongousObjects.TestHumongousThreshold 57 * 58 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 59 * -Xms128M -XX:G1HeapRegionSize=16M 60 * gc.g1.humongousObjects.TestHumongousThreshold 61 * 62 * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. 63 * -Xms200M -XX:G1HeapRegionSize=32M 64 * gc.g1.humongousObjects.TestHumongousThreshold 65 * 66 */ 67 68 public class TestHumongousThreshold { 69 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 70 private static final int REGION_SIZE = WHITE_BOX.g1RegionSize(); 71 private static final int MAX_CONTINUOUS_SIZE_CHECK = 129; 72 private static final int NON_HUMONGOUS_DIVIDER = 10; 73 74 /** 75 * The method allocates byte[] with specified size and checks that: 76 * 1. byte[] is allocated as we specified in expectedHumongous. 77 * 2. byte[] is allocated as humongous if its size is large than a half of region and non-humongous otherwise. 78 * It uses WB to obtain the size of created byte[]. Only objects larger than half of region are expected 79 * to be humongous. 80 * 81 * @param arraySize size of allocation 82 * @param expectedHumongous expected humongous/non-humongous allocation 83 * @return allocated byte array 84 */ 85 86 private static byte[] allocateAndCheck(int arraySize, boolean expectedHumongous) { 87 byte[] storage = new byte[arraySize]; 88 long objectSize = WHITE_BOX.getObjectSize(storage); 89 boolean shouldBeHumongous = objectSize > (REGION_SIZE / 2); 90 91 Asserts.assertEquals(expectedHumongous, shouldBeHumongous, "Despite we expected this object to be " 92 + (expectedHumongous ? "humongous" : "non-humongous") + " it appeared otherwise when we checked " 93 + "object size - likely test bug; Allocation size = " + arraySize + "; Object size = " + objectSize 94 + "; region size = " + REGION_SIZE); 95 96 Asserts.assertEquals(WHITE_BOX.g1IsHumongous(storage), shouldBeHumongous, 97 "Object should be allocated as " + (shouldBeHumongous ? "humongous" 98 : "non-humongous") + " but it wasn't; Allocation size = " + arraySize + "; Object size = " 99 + objectSize + "; region size = " + REGION_SIZE); 100 return storage; 101 } 102 103 public static void main(String[] args) { 104 int byteArrayMemoryOverhead = Helpers.detectByteArrayAllocationOverhead(); 105 106 // Largest non-humongous byte[] 107 int maxByteArrayNonHumongousSize = (REGION_SIZE / 2) - byteArrayMemoryOverhead; 108 109 // Increment for non-humongous testing 110 int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_DIVIDER; 111 112 // Maximum byte[] that takes one region 113 int maxByteArrayOneRegionSize = REGION_SIZE - byteArrayMemoryOverhead; 114 115 // Sizes in regions 116 // i,e, 1.0f means one region, 1.5f means one and half region etc 117 float[] humongousFactors = {0.8f, 1.0f, 1.2f, 1.5f, 1.7f, 2.0f, 2.5f}; 118 119 // Some diagnostic output 120 System.out.format("%s started%n", TestHumongousThreshold.class.getName()); 121 System.out.format("Actual G1 region size %d%n", REGION_SIZE); 122 System.out.format("byte[] memory overhead %d%n", byteArrayMemoryOverhead); 123 124 // Non-humongous allocations 125 System.out.format("Doing non-humongous allocations%n"); 126 127 // Testing allocations with byte[] with length from 0 to MAX_CONTINUOUS_SIZE_CHECK 128 System.out.format("Testing allocations with byte[] with length from 0 to %d%n", MAX_CONTINUOUS_SIZE_CHECK); 129 for (int i = 0; i < MAX_CONTINUOUS_SIZE_CHECK; ++i) { 130 allocateAndCheck(i, false); 131 } 132 133 // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_DIVIDER 134 System.out.format("Testing allocations with byte[] with length from 0 to %d with step %d%n", 135 nonHumongousStep * NON_HUMONGOUS_DIVIDER, nonHumongousStep); 136 for (int i = 0; i < NON_HUMONGOUS_DIVIDER; ++i) { 137 allocateAndCheck(i * nonHumongousStep, false); 138 } 139 140 // Testing allocations with byte[] of maximum non-humongous length 141 System.out.format("Testing allocations with byte[] of maximum non-humongous length %d%n", 142 maxByteArrayNonHumongousSize); 143 allocateAndCheck(maxByteArrayNonHumongousSize, false); 144 145 // Humongous allocations 146 System.out.format("Doing humongous allocations%n"); 147 // Testing with minimum humongous object 148 System.out.format("Testing with byte[] of minimum humongous object %d%n", maxByteArrayNonHumongousSize + 1); 149 allocateAndCheck(maxByteArrayNonHumongousSize + 1, true); 150 151 // Testing allocations with byte[] with length from (maxByteArrayNonHumongousSize + 1) to 152 // (maxByteArrayNonHumongousSize + 1 + MAX_CONTINUOUS_SIZE_CHECK) 153 System.out.format("Testing allocations with byte[] with length from %d to %d%n", 154 maxByteArrayNonHumongousSize + 1, maxByteArrayNonHumongousSize + 1 + MAX_CONTINUOUS_SIZE_CHECK); 155 for (int i = 0; i < MAX_CONTINUOUS_SIZE_CHECK; ++i) { 156 allocateAndCheck(maxByteArrayNonHumongousSize + 1 + i, true); 157 } 158 159 // Checking that large (more than a half of region size) objects are humongous 160 System.out.format("Checking that large (more than a half of region size) objects are humongous%n"); 161 for (float factor : humongousFactors) { 162 allocateAndCheck((int) (maxByteArrayOneRegionSize * factor), true); 163 } 164 } 165 }