test/gc/g1/TestShrinkAuxiliaryData.java

Mon, 06 Nov 2017 16:51:47 +0800

author
aoqi
date
Mon, 06 Nov 2017 16:51:47 +0800
changeset 7997
6cbff0651f1a
parent 7835
e5406a79ae90
permissions
-rw-r--r--

[Code Reorganization] remove trailing whitespace to pass jcheck test

     1 /*
     2  * Copyright (c) 2014, 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  */
    24 import com.oracle.java.testlibrary.Asserts;
    25 import com.oracle.java.testlibrary.OutputAnalyzer;
    26 import com.oracle.java.testlibrary.Platform;
    27 import com.oracle.java.testlibrary.ProcessTools;
    28 import com.oracle.java.testlibrary.Utils;
    29 import java.io.IOException;
    30 import java.lang.management.ManagementFactory;
    31 import java.lang.management.MemoryUsage;
    32 import java.text.DecimalFormat;
    33 import java.text.DecimalFormatSymbols;
    34 import java.util.ArrayList;
    35 import java.util.Arrays;
    36 import java.util.Collections;
    37 import java.util.LinkedList;
    38 import java.util.List;
    39 import sun.misc.Unsafe; // for ADDRESS_SIZE
    40 import sun.hotspot.WhiteBox;
    42 public class TestShrinkAuxiliaryData {
    44     private static final int REGION_SIZE = 1024 * 1024;
    46     private final static String[] initialOpts = new String[]{
    47         "-XX:MinHeapFreeRatio=10",
    48         "-XX:MaxHeapFreeRatio=11",
    49         "-XX:+UseG1GC",
    50         "-XX:G1HeapRegionSize=" + REGION_SIZE,
    51         "-XX:-ExplicitGCInvokesConcurrent",
    52         "-XX:+PrintGCDetails",
    53         "-XX:+UnlockDiagnosticVMOptions",
    54         "-XX:+WhiteBoxAPI",
    55         "-Xbootclasspath/a:.",
    56     };
    58     private final int hotCardTableSize;
    60     protected TestShrinkAuxiliaryData(int hotCardTableSize) {
    61         this.hotCardTableSize = hotCardTableSize;
    62     }
    64     protected void test() throws Exception {
    65         ArrayList<String> vmOpts = new ArrayList();
    66         Collections.addAll(vmOpts, initialOpts);
    68         int maxCacheSize = Math.max(0, Math.min(31, getMaxCacheSize()));
    69         if (maxCacheSize < hotCardTableSize) {
    70             System.out.format("Skiping test for %d cache size due max cache size %d",
    71                     hotCardTableSize, maxCacheSize
    72             );
    73             return;
    74         }
    76         printTestInfo(maxCacheSize);
    78         vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
    79         vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
    81         // for 32 bits ObjectAlignmentInBytes is not a option
    82         if (Platform.is32bit()) {
    83             ArrayList<String> vmOptsWithoutAlign = new ArrayList(vmOpts);
    84             vmOptsWithoutAlign.add(ShrinkAuxiliaryDataTest.class.getName());
    85             performTest(vmOptsWithoutAlign);
    86             return;
    87         }
    89         for (int alignment = 3; alignment <= 8; alignment++) {
    90             ArrayList<String> vmOptsWithAlign = new ArrayList(vmOpts);
    91             vmOptsWithAlign.add("-XX:ObjectAlignmentInBytes="
    92                     + (int) Math.pow(2, alignment));
    93             vmOptsWithAlign.add(ShrinkAuxiliaryDataTest.class.getName());
    95             performTest(vmOptsWithAlign);
    96         }
    97     }
    99     private void performTest(List<String> opts) throws Exception {
   100         ProcessBuilder pb
   101                 = ProcessTools.createJavaProcessBuilder(
   102                         opts.toArray(new String[opts.size()])
   103                 );
   105         OutputAnalyzer output = new OutputAnalyzer(pb.start());
   106         System.out.println(output.getStdout());
   107         System.err.println(output.getStderr());
   108         output.shouldHaveExitValue(0);
   109     }
   111     private void printTestInfo(int maxCacheSize) {
   113         DecimalFormat grouped = new DecimalFormat("000,000");
   114         DecimalFormatSymbols formatSymbols = grouped.getDecimalFormatSymbols();
   115         formatSymbols.setGroupingSeparator(' ');
   116         grouped.setDecimalFormatSymbols(formatSymbols);
   118         System.out.format(
   119                 "Test will use %s bytes of memory of %s available%n"
   120                 + "Available memory is %s with %d bytes pointer size - can save %s pointers%n"
   121                 + "Max cache size: 2^%d = %s elements%n",
   122                 grouped.format(ShrinkAuxiliaryDataTest.getMemoryUsedByTest()),
   123                 grouped.format(Runtime.getRuntime().maxMemory()),
   124                 grouped.format(Runtime.getRuntime().maxMemory()
   125                         - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()),
   126                 Unsafe.ADDRESS_SIZE,
   127                 grouped.format((Runtime.getRuntime().freeMemory()
   128                         - ShrinkAuxiliaryDataTest.getMemoryUsedByTest())
   129                         / Unsafe.ADDRESS_SIZE),
   130                 maxCacheSize,
   131                 grouped.format((int) Math.pow(2, maxCacheSize))
   132         );
   133     }
   135     /**
   136      * Detects maximum possible size of G1ConcRSLogCacheSize available for
   137      * current process based on maximum available process memory size
   138      *
   139      * @return power of two
   140      */
   141     private static int getMaxCacheSize() {
   142         long availableMemory = Runtime.getRuntime().freeMemory()
   143                 - ShrinkAuxiliaryDataTest.getMemoryUsedByTest() - 1l;
   144         if (availableMemory <= 0) {
   145             return 0;
   146         }
   148         long availablePointersCount = availableMemory / Unsafe.ADDRESS_SIZE;
   149         return (63 - (int) Long.numberOfLeadingZeros(availablePointersCount));
   150     }
   152     static class ShrinkAuxiliaryDataTest {
   154         public static void main(String[] args) throws IOException {
   156             ShrinkAuxiliaryDataTest testCase = new ShrinkAuxiliaryDataTest();
   158             if (!testCase.checkEnvApplicability()) {
   159                 return;
   160             }
   162             testCase.test();
   163         }
   165         /**
   166          * Checks is this environment suitable to run this test
   167          * - memory is enough to decommit (page size is not big)
   168          * - RSet cache size is not too big
   169          *
   170          * @return true if test could run, false if test should be skipped
   171          */
   172         protected boolean checkEnvApplicability() {
   174             int pageSize = WhiteBox.getWhiteBox().getVMPageSize();
   175             System.out.println( "Page size = " + pageSize
   176                     + " region size = " + REGION_SIZE
   177                     + " aux data ~= " + (REGION_SIZE * 3 / 100));
   178             // If auxdata size will be less than page size it wouldn't decommit.
   179             // Auxiliary data size is about ~3.6% of heap size.
   180             if (pageSize >= REGION_SIZE * 3 / 100) {
   181                 System.out.format("Skipping test for too large page size = %d",
   182                        pageSize
   183                 );
   184                 return false;
   185             }
   187             if (REGION_SIZE * REGIONS_TO_ALLOCATE > Runtime.getRuntime().maxMemory()) {
   188                 System.out.format("Skipping test for too low available memory. "
   189                         + "Need %d, available %d",
   190                         REGION_SIZE * REGIONS_TO_ALLOCATE,
   191                         Runtime.getRuntime().maxMemory()
   192                 );
   193                 return false;
   194             }
   196             return true;
   197         }
   199         class GarbageObject {
   201             private final List<byte[]> payload = new ArrayList();
   202             private final List<GarbageObject> ref = new LinkedList();
   204             public GarbageObject(int size) {
   205                 payload.add(new byte[size]);
   206             }
   208             public void addRef(GarbageObject g) {
   209                 ref.add(g);
   210             }
   212             public void mutate() {
   213                 if (!payload.isEmpty() && payload.get(0).length > 0) {
   214                     payload.get(0)[0] = (byte) (Math.random() * Byte.MAX_VALUE);
   215                 }
   216             }
   217         }
   219         private final List<GarbageObject> garbage = new ArrayList();
   221         public void test() throws IOException {
   223             MemoryUsage muFull, muFree, muAuxDataFull, muAuxDataFree;
   224             float auxFull, auxFree;
   226             allocate();
   227             link();
   228             mutate();
   230             muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
   231             long numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions()
   232                     - WhiteBox.getWhiteBox().g1NumFreeRegions();
   233             muAuxDataFull = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage();
   234             auxFull = (float)muAuxDataFull.getUsed() / numUsedRegions;
   236             System.out.format("Full aux data  ratio= %f, regions max= %d, used= %d\n",
   237                     auxFull, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
   238             );
   240             deallocate();
   241             System.gc();
   243             muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
   244             muAuxDataFree = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage();
   246             numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions()
   247                     - WhiteBox.getWhiteBox().g1NumFreeRegions();
   248             auxFree = (float)muAuxDataFree.getUsed() / numUsedRegions;
   250             System.out.format("Free aux data ratio= %f, regions max= %d, used= %d\n",
   251                     auxFree, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
   252             );
   254             Asserts.assertLessThanOrEqual(muFree.getCommitted(), muFull.getCommitted(),
   255                     String.format("heap decommit failed - full > free: %d > %d",
   256                             muFree.getCommitted(), muFull.getCommitted()
   257                     )
   258             );
   260             System.out.format("State               used   committed\n");
   261             System.out.format("Full aux data: %10d %10d\n", muAuxDataFull.getUsed(), muAuxDataFull.getCommitted());
   262             System.out.format("Free aux data: %10d %10d\n", muAuxDataFree.getUsed(), muAuxDataFree.getCommitted());
   264             // if decommited check that aux data has same ratio
   265             if (muFree.getCommitted() < muFull.getCommitted()) {
   266                 Asserts.assertLessThanOrEqual(auxFree, auxFull,
   267                         String.format("auxiliary data decommit failed - full > free: %f > %f",
   268                                 auxFree, auxFull
   269                         )
   270                 );
   271             }
   272         }
   274         private void allocate() {
   275             for (int r = 0; r < REGIONS_TO_ALLOCATE; r++) {
   276                 for (int i = 0; i < NUM_OBJECTS_PER_REGION; i++) {
   277                     GarbageObject g = new GarbageObject(REGION_SIZE
   278                             / NUM_OBJECTS_PER_REGION);
   279                     garbage.add(g);
   280                 }
   281             }
   282         }
   284         /**
   285          * Iterate through all allocated objects, and link to objects in another
   286          * regions
   287          */
   288         private void link() {
   289             for (int ig = 0; ig < garbage.size(); ig++) {
   290                 int regionNumber = ig / NUM_OBJECTS_PER_REGION;
   292                 for (int i = 0; i < NUM_LINKS; i++) {
   293                     int regionToLink;
   294                     do {
   295                         regionToLink = (int) (Math.random() * REGIONS_TO_ALLOCATE);
   296                     } while (regionToLink == regionNumber);
   298                     // get random garbage object from random region
   299                     garbage.get(ig).addRef(garbage.get(regionToLink
   300                             * NUM_OBJECTS_PER_REGION + (int) (Math.random()
   301                             * NUM_OBJECTS_PER_REGION)));
   302                 }
   303             }
   304         }
   306         private void mutate() {
   307             for (int ig = 0; ig < garbage.size(); ig++) {
   308                 garbage.get(ig).mutate();
   309             }
   310         }
   312         private void deallocate() {
   313             garbage.clear();
   314             System.gc();
   315         }
   317         static long getMemoryUsedByTest() {
   318             return REGIONS_TO_ALLOCATE * REGION_SIZE;
   319         }
   321         private static final int REGIONS_TO_ALLOCATE = 100;
   322         private static final int NUM_OBJECTS_PER_REGION = 10;
   323         private static final int NUM_LINKS = 20; // how many links create for each object
   324     }
   325 }

mercurial