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 }