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