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