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