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  * @test TestNewRatioFlag
  26  * @key gc
  27  * @bug 8025166
  28  * @summary Verify that heap devided among generations according to NewRatio
  29  * @requires vm.gc != "Z"
  30  * @library /test/lib
  31  * @modules java.base/jdk.internal.misc
  32  *          java.management
  33  * @build sun.hotspot.WhiteBox
  34  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  35  * @run driver TestNewRatioFlag
  36  */
  37 
  38 import java.util.Arrays;
  39 import java.util.Collections;
  40 import java.util.LinkedList;
  41 import jdk.test.lib.process.ProcessTools;
  42 import jdk.test.lib.process.OutputAnalyzer;
  43 import jdk.test.lib.Utils;
  44 import sun.hotspot.WhiteBox;
  45 
  46 public class TestNewRatioFlag {
  47 
  48     public static final long M = 1024 * 1024;
  49     public static final long HEAP_SIZE = 100 * M;
  50 
  51     public static void main(String args[]) throws Exception {
  52         LinkedList<String> options = new LinkedList<>(
  53                 Arrays.asList(Utils.getFilteredTestJavaOpts("(-XX:[^ ]*NewSize=[^ ]+)|(-Xm[ns][^ ]+)"))
  54         );
  55 
  56         testNewRatio(4, options);
  57         testNewRatio(6, options);
  58         testNewRatio(10, options);
  59         testNewRatio(15, options);
  60         testNewRatio(20, options);
  61     }
  62 
  63     /**
  64      * Verify that actual size of young gen conforms specified NewRatio
  65      *
  66      * @param ratio value of NewRatio option
  67      * @param options additional options for VM
  68      */
  69     public static void testNewRatio(int ratio, LinkedList<String> options) throws Exception {
  70         LinkedList<String> vmOptions = new LinkedList<>(options);
  71         Collections.addAll(vmOptions,
  72                 "-Xbootclasspath/a:.",
  73                 "-XX:+UnlockDiagnosticVMOptions",
  74                 "-XX:+WhiteBoxAPI",
  75                 "-XX:GCLockerEdenExpansionPercent=0",
  76                 "-Xmx" + HEAP_SIZE,
  77                 "-Xms" + HEAP_SIZE,
  78                 "-XX:NewRatio=" + ratio,
  79                 "-XX:-UseLargePages",
  80                 NewRatioVerifier.class.getName(),
  81                 Integer.toString(ratio)
  82         );
  83 
  84         ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
  85         OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
  86         analyzer.shouldHaveExitValue(0);
  87         System.out.println(analyzer.getOutput());
  88     }
  89 
  90     public static class NewRatioVerifier {
  91 
  92         static WhiteBox wb = WhiteBox.getWhiteBox();
  93 
  94         public static void main(String args[]) {
  95             if (args.length != 1) {
  96                 throw new IllegalArgumentException("Expected 1 arg: <expectedRatio>");
  97             }
  98             int expectedRatio = Integer.valueOf(args[0]);
  99             switch (GCTypes.YoungGCType.getYoungGCType()) {
 100                 case DefNew:
 101                 case ParNew:
 102                     verifyDefNewNewRatio(expectedRatio);
 103                     break;
 104                 case PSNew:
 105                     verifyPSNewRatio(expectedRatio);
 106                     break;
 107                 case G1:
 108                     verifyG1NewRatio(expectedRatio);
 109                     break;
 110                 default:
 111                     throw new RuntimeException("Unexpected young GC type");
 112             }
 113         }
 114 
 115         /**
 116          * Verify NewSize for DefNew and ParNew collectors.
 117          *
 118          * Compare expected NewSize calculated according to sizing policies used by DefNew
 119          * with NewSize value reported by MemoryPoolMXBeans.
 120          */
 121         public static void verifyDefNewNewRatio(int expectedRatio) {
 122             long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
 123             long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
 124             long initOld = HeapRegionUsageTool.getOldUsage().getInit();
 125 
 126             long newSize = initEden + 2 * initSurv;
 127 
 128             long expectedNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio,
 129                     wb.getHeapSpaceAlignment());
 130 
 131             if (expectedNewSize != newSize) {
 132                 throw new RuntimeException("Expected young gen size is: " + expectedNewSize
 133                         + ", but observed new size is: " + newSize);
 134             }
 135         }
 136 
 137         /**
 138          * Verify NewSize for PS collector.
 139          * Expected NewSize calculated according to alignment policies used by PS
 140          * and then compared with actual NewSize obtained from MemoryPoolMXBeans.
 141          */
 142         public static void verifyPSNewRatio(int expectedRatio) {
 143             long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
 144             long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
 145             long initOld = HeapRegionUsageTool.getOldUsage().getInit();
 146 
 147             long newSize = initEden + 2 * initSurv;
 148 
 149             long alignedDownNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio,
 150                     wb.getHeapSpaceAlignment());
 151             long expectedNewSize = HeapRegionUsageTool.alignUp(alignedDownNewSize,
 152                     wb.psVirtualSpaceAlignment());
 153 
 154             if (expectedNewSize != newSize) {
 155                 throw new RuntimeException("Expected young gen size is: " + expectedNewSize
 156                         + ", but observed new size is: " + newSize);
 157             }
 158         }
 159 
 160         /**
 161          * Verify NewSize for G1 GC.
 162          * Amount of young regions calculated according to sizing policies used by G1
 163          * and then compared with actual number of young regions derived from
 164          * values reported by MemoryPoolMXBeans and region size.
 165          */
 166         public static void verifyG1NewRatio(int expectedRatio) {
 167             long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
 168             long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
 169             long maxOld = HeapRegionUsageTool.getOldUsage().getMax();
 170 
 171             int regionSize = wb.g1RegionSize();
 172             int youngListLength = (int) ((initEden + initSurv) / regionSize);
 173             int maxRegions = (int) (maxOld / regionSize);
 174             int expectedYoungListLength = (int) (maxRegions / (double) (expectedRatio + 1));
 175 
 176             if (youngListLength != expectedYoungListLength) {
 177                 throw new RuntimeException("Expected G1 young list length is: " + expectedYoungListLength
 178                         + ", but observed young list length is: " + youngListLength);
 179             }
 180         }
 181     }
 182 }