test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java
changeset 50223 28a33a0dbf04
child 50404 5193c6b98cc7
equal deleted inserted replaced
50222:911b913022ef 50223:28a33a0dbf04
       
     1 /*
       
     2  * Copyright (c) 2013, 2018, 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 package metaspace.gc;
       
    25 
       
    26 import java.util.Arrays;
       
    27 import vm.share.VMRuntimeEnvUtils;
       
    28 
       
    29 /**
       
    30  * Test metaspace ergonomic.
       
    31  *
       
    32  * <ul>
       
    33  * <li>MetaspaceSize
       
    34  * <li>MaxMetaspaceSize
       
    35  * <li>MinMetaspaceFreeRatio
       
    36  * <li>MaxMetaspaceFreeRatio
       
    37  * </ul>
       
    38  *
       
    39  * The test loads classes until the committed metaspace achieves the certain
       
    40  * level between MetaspaceSize and MaxMetaspaceSize.
       
    41  * Then it counts how many times GC has been induced.
       
    42  * Test verifies that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
       
    43  * affect the frequency of GC. (High-water mark)
       
    44  *
       
    45  * Note: The test doesn't check the GC count if CMS is used.
       
    46  *
       
    47  * Quoting: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
       
    48  * <pre>
       
    49  * Class metadata is deallocated when the corresponding Java class is unloaded.
       
    50  * Java classes are unloaded as a results of garbage collection and garbage
       
    51  * collections may be induced in order to unload classes and deallocate class
       
    52  * metadata. When the space used for class metadata reaches a certain level
       
    53  * (call it a high-water mark), a garbage collection is induced.
       
    54  * After the garbage collection the high-water mark may be raised or lowered
       
    55  * depending on the amount of space freed from class metadata. The high-water
       
    56  * mark would be raised so as not to induce another garbage collection too soon.
       
    57  * The high-water mark is initially set to the value of the command-line
       
    58  * flag MetaspaceSize . It is raised or lowered based on the flags
       
    59  * MaxMetaspaceFreeRatio and MinMetaspaceFreeRatio.
       
    60  * If the committed space available for class metadata as a percentage of
       
    61  * the total committed space for class metadata is greater than
       
    62  * MaxMetaspaceFreeRatio, the high-water mark will be lowered.
       
    63  * If it is less than MinMetaspaceFreeRatio, the high-water mark will be raised.
       
    64  * </pre>
       
    65  */
       
    66 public class HighWaterMarkTest extends FirstGCTest {
       
    67 
       
    68     public static void main(String... args) {
       
    69         new HighWaterMarkTest().run(args);
       
    70     }
       
    71 
       
    72     // value given in -XX:MetaspaceSize=<value>
       
    73     private long metaspaceSize = -1;
       
    74 
       
    75     // value given in -XX:MaxMetaspaceSize=<value>
       
    76     private long maxMetaspaceSize = -1;
       
    77 
       
    78     // value given in -XX:MinMetaspaceFreeRatio=<value>
       
    79     private long minMetaspaceFreeRatio = -1;
       
    80 
       
    81     // value given in -XX:MaxMetaspaceFreeRatio=<value>
       
    82     private long maxMetaspaceFreeRatio = -1;
       
    83 
       
    84     /**
       
    85      * Parses arguments and vm options.
       
    86      * Throws Fault in cases of wrong values or missed parameters.
       
    87      *
       
    88      * @param args command line options
       
    89      */
       
    90     @Override
       
    91     protected void parseArgs(String[] args) {
       
    92         if (args.length > 0) {
       
    93             printUsage();
       
    94             throw new Fault("Illegal arguments: " + Arrays.asList(args));
       
    95         }
       
    96 
       
    97         if (gclogFileName == null) {
       
    98             printUsage();
       
    99             throw new Fault("Log file name is not given");
       
   100         }
       
   101 
       
   102         final String metaSize    = "-XX:MetaspaceSize=";
       
   103         final String maxMetaSize = "-XX:MaxMetaspaceSize=";
       
   104         final String minRatio    = "-XX:MinMetaspaceFreeRatio=";
       
   105         final String maxRatio    = "-XX:MaxMetaspaceFreeRatio=";
       
   106 
       
   107         for (String va: vmArgs) {
       
   108             if (va.startsWith(metaSize)) {
       
   109                 metaspaceSize = parseValue(va.substring(metaSize.length()));
       
   110             } else if (va.startsWith(maxMetaSize)) {
       
   111                 maxMetaspaceSize = parseValue(va.substring(maxMetaSize.length()));
       
   112             } else if (va.startsWith(minRatio)) {
       
   113                 minMetaspaceFreeRatio = parseValue(va.substring(minRatio.length()));
       
   114             } else if (va.startsWith(maxRatio)) {
       
   115                 maxMetaspaceFreeRatio = parseValue(va.substring(maxRatio.length()));
       
   116             }
       
   117         }
       
   118 
       
   119         if (metaspaceSize < 0) {
       
   120             printUsage();
       
   121             throw new Fault("-XX:MetaspaceSize is not specified");
       
   122         } else if (maxMetaspaceSize < 0) {
       
   123             printUsage();
       
   124             throw new Fault("-XX:MaxMetaspaceSize is not specified");
       
   125         } else if (minMetaspaceFreeRatio < 0) {
       
   126             printUsage();
       
   127             throw new Fault("-XX:MinMetaspaceFreeRatio is not specified");
       
   128         } else if (maxMetaspaceFreeRatio < 0) {
       
   129             printUsage();
       
   130             throw new Fault("-XX:MaxMetaspaceFreeRatio is not specified");
       
   131         }
       
   132 
       
   133     }
       
   134 
       
   135     private void printUsage() {
       
   136         System.err.println("Usage: ");
       
   137         System.err.println("java [-Xlog:gc:<filename>] [-XX:MetaspaceSize=..] [-XX:MaxMetaspaceSize=..] [-XX:MinMetaspaceFreeRatio=..] [-XX:MaxMetaspaceFreeRatio=..] \\");
       
   138         System.err.println("    " + HighWaterMarkTest.class.getCanonicalName());
       
   139     }
       
   140 
       
   141     /**
       
   142      * Check that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
       
   143      * affects the moment of the next GC.
       
   144      *
       
   145      * Eats memory until amount of committed metaspace achieves a certain level
       
   146      * (between MetaspaceSize and MaxMetaspaceSize).
       
   147      * Then checks how many times GC has been invoked.
       
   148      *
       
   149      */
       
   150     @Override
       
   151     public void doCheck() {
       
   152 
       
   153         // to avoid timeouts we limit the number of attempts
       
   154         int attempts = 0;
       
   155         int maxAttempts = 10_000;
       
   156 
       
   157         // in between metaspaceSize and maxMetaspaceSize
       
   158         // no OOM is exepcted.
       
   159         long committedLevel = (metaspaceSize + maxMetaspaceSize) / 2;
       
   160 
       
   161         while (getCommitted() < committedLevel && attempts < maxAttempts) {
       
   162             attempts++;
       
   163             loadNewClasses(9, true);  // load classes and keep references
       
   164             loadNewClasses(1, false); // load classes without keeping references
       
   165         }
       
   166 
       
   167 
       
   168         System.out.println("% Classes loaded: " + attempts*10);
       
   169         System.out.println("% Used metaspace    : " + bytes2k(getUsed()));
       
   170         System.out.println("% Committed metaspce: " + bytes2k(getCommitted()));
       
   171 
       
   172         cleanLoadedClasses();
       
   173 
       
   174         if (attempts == maxAttempts) {
       
   175             throw new Fault("Committed amount hasn't achieved " + bytes2k(committedLevel));
       
   176         }
       
   177 
       
   178         if (VMRuntimeEnvUtils.isVMOptionEnabled("UseConcMarkSweepGC")) {
       
   179             System.out.println("ConcMarkSweep is used, cannot count GC");
       
   180             return;
       
   181         }
       
   182 
       
   183         int gcCount = getMetaspaceGCCount();
       
   184         if (gcCount < 0) {
       
   185             // perhpas, it's better to silently pass here... Let's see.
       
   186             throw new Fault ("Unable to count full collections, could be an env issue");
       
   187         }
       
   188         System.out.println("% GC has been invoked: " + gcCount + " times");
       
   189 
       
   190         if (VMRuntimeEnvUtils.isVMOptionEnabled("UseG1GC") &&
       
   191               VMRuntimeEnvUtils.isVMOptionEnabled("ClassUnloadingWithConcurrentMark")) {
       
   192             System.out.println("% isG1ClassUnloading: true");
       
   193             if (gcCount != 0) {
       
   194                 throw new Fault ("G1 should unload classes, full GC is not expected");
       
   195             }
       
   196         } else {
       
   197             if (maxMetaspaceFreeRatio <= 1) {
       
   198                 // min/max = 0/1  boundary value
       
   199                 // GC should happen very often
       
   200                 checkGCCount(gcCount, 20, -1);
       
   201             } else if (minMetaspaceFreeRatio >= 99) {
       
   202                 // min/max = 99/100  boundary value
       
   203                 // GC should happen very rare
       
   204                 checkGCCount(gcCount, -1, 2);
       
   205             } else if (minMetaspaceFreeRatio >= 10  && maxMetaspaceFreeRatio <= 20) {
       
   206                 // GC should happen quite often
       
   207                 checkGCCount(gcCount, 3, 30);
       
   208             } else if (minMetaspaceFreeRatio >= 70  && maxMetaspaceFreeRatio <= 80) {
       
   209                 // GC should happen quite often
       
   210                 checkGCCount(gcCount, 1, 3);
       
   211             } else {
       
   212                 // hard to estimate
       
   213             }
       
   214         }
       
   215 
       
   216     }
       
   217     /**
       
   218      * Checks that count of GC fits the expected range.
       
   219      * Throws Fault if count is unexpected.
       
   220      *
       
   221      * @param count how many times GC has happened
       
   222      * @param min   expected minimum, if under zero - undefined
       
   223      * @param max   expected maximum, if under zero - undefined
       
   224      */
       
   225     void checkGCCount(int count, int min, int max) {
       
   226         if (min < 0) {
       
   227             if(count > max) {
       
   228                 throw new Fault("GC has happened too often: " + count + " times, " +
       
   229                         "expected count: less than " + max);
       
   230             }
       
   231         } else if (max < 0) {
       
   232             if(count < min) {
       
   233                 throw new Fault("GC has happened too rare: " + count + " times, " +
       
   234                         "expected count greater than " + min);
       
   235             }
       
   236         } else if (count < min || count > max ) {
       
   237             throw new Fault ("GC has happened " + count + " times, " +
       
   238                     "approximate count is " + min + " to " + max);
       
   239         }
       
   240     }
       
   241 
       
   242 }