test/gc/g1/TestShrinkDefragmentedHeap.java

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

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

[Code Reorganization] remove trailing whitespace to pass jcheck test

jwilhelm@7174 1 /*
jwilhelm@7174 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
jwilhelm@7174 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jwilhelm@7174 4 *
jwilhelm@7174 5 * This code is free software; you can redistribute it and/or modify it
jwilhelm@7174 6 * under the terms of the GNU General Public License version 2 only, as
jwilhelm@7174 7 * published by the Free Software Foundation.
jwilhelm@7174 8 *
jwilhelm@7174 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jwilhelm@7174 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jwilhelm@7174 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jwilhelm@7174 12 * version 2 for more details (a copy is included in the LICENSE file that
jwilhelm@7174 13 * accompanied this code).
jwilhelm@7174 14 *
jwilhelm@7174 15 * You should have received a copy of the GNU General Public License version
jwilhelm@7174 16 * 2 along with this work; if not, write to the Free Software Foundation,
jwilhelm@7174 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jwilhelm@7174 18 *
jwilhelm@7174 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jwilhelm@7174 20 * or visit www.oracle.com if you need additional information or have any
jwilhelm@7174 21 * questions.
jwilhelm@7174 22 */
jwilhelm@7174 23
jwilhelm@7174 24 /**
jwilhelm@7174 25 * @test TestShrinkDefragmentedHeap
jwilhelm@7174 26 * @bug 8038423
jwilhelm@7174 27 * @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects
jwilhelm@7174 28 * 1. allocate small objects mixed with humongous ones
jwilhelm@7174 29 * "ssssHssssHssssHssssHssssHssssHssssH"
jwilhelm@7174 30 * 2. release all allocated object except the last humongous one
jwilhelm@7174 31 * "..................................H"
jwilhelm@7174 32 * 3. invoke gc and check that memory returned to the system (amount of committed memory got down)
jwilhelm@7174 33 *
jwilhelm@7174 34 * @library /testlibrary
jwilhelm@7174 35 */
jwilhelm@7174 36 import java.lang.management.ManagementFactory;
jwilhelm@7174 37 import java.lang.management.MemoryUsage;
jwilhelm@7174 38 import java.util.ArrayList;
jwilhelm@7174 39 import java.util.List;
jwilhelm@7174 40 import sun.management.ManagementFactoryHelper;
jwilhelm@7174 41 import static com.oracle.java.testlibrary.Asserts.*;
jwilhelm@7174 42 import com.oracle.java.testlibrary.ProcessTools;
jwilhelm@7174 43 import com.oracle.java.testlibrary.OutputAnalyzer;
jwilhelm@7174 44
jwilhelm@7174 45 public class TestShrinkDefragmentedHeap {
jwilhelm@7174 46 // Since we store all the small objects, they become old and old regions are also allocated at the bottom of the heap
jwilhelm@7174 47 // together with humongous regions. So if there are a lot of old regions in the lower part of the heap,
jwilhelm@7174 48 // the humongous regions will be allocated in the upper part of the heap anyway.
jwilhelm@7174 49 // To avoid this the Eden needs to be big enough to fit all the small objects.
jwilhelm@7174 50 private static final int INITIAL_HEAP_SIZE = 200 * 1024 * 1024;
jwilhelm@7174 51 private static final int MINIMAL_YOUNG_SIZE = 190 * 1024 * 1024;
jwilhelm@7174 52 private static final int REGION_SIZE = 1 * 1024 * 1024;
jwilhelm@7174 53
jwilhelm@7174 54 public static void main(String[] args) throws Exception, Throwable {
jwilhelm@7174 55 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
jwilhelm@7174 56 "-XX:InitialHeapSize=" + INITIAL_HEAP_SIZE,
jwilhelm@7174 57 "-Xmn" + MINIMAL_YOUNG_SIZE,
jwilhelm@7174 58 "-XX:MinHeapFreeRatio=10",
jwilhelm@7174 59 "-XX:MaxHeapFreeRatio=11",
jwilhelm@7174 60 "-XX:+UseG1GC",
jwilhelm@7174 61 "-XX:G1HeapRegionSize=" + REGION_SIZE,
azakharov@7337 62 "-XX:-ExplicitGCInvokesConcurrent",
jwilhelm@7174 63 "-verbose:gc",
jwilhelm@7174 64 GCTest.class.getName()
jwilhelm@7174 65 );
jwilhelm@7174 66
jwilhelm@7174 67 OutputAnalyzer output = ProcessTools.executeProcess(pb);
jwilhelm@7174 68 output.shouldHaveExitValue(0);
jwilhelm@7174 69 }
jwilhelm@7174 70
jwilhelm@7174 71 static class GCTest {
jwilhelm@7174 72
jwilhelm@7174 73 private static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";
jwilhelm@7174 74 private static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";
jwilhelm@7174 75 private static final String NEW_SIZE_FLAG_NAME = "NewSize";
jwilhelm@7174 76
jwilhelm@7174 77 private static final ArrayList<ArrayList<byte[]>> garbage = new ArrayList<>();
jwilhelm@7174 78
jwilhelm@7174 79 private static final int SMALL_OBJS_SIZE = 10 * 1024; // 10kB
jwilhelm@7174 80 private static final int SMALL_OBJS_COUNT = MINIMAL_YOUNG_SIZE / (SMALL_OBJS_SIZE-1);
jwilhelm@7174 81 private static final int ALLOCATE_COUNT = 3;
jwilhelm@7174 82 // try to put all humongous object into gap between min young size and initial heap size
jwilhelm@7174 83 // to avoid implicit GCs
jwilhelm@7174 84 private static final int HUMONG_OBJS_SIZE = (int) Math.max(
jwilhelm@7174 85 (INITIAL_HEAP_SIZE - MINIMAL_YOUNG_SIZE) / ALLOCATE_COUNT / 4,
jwilhelm@7174 86 REGION_SIZE * 1.1
jwilhelm@7174 87 );
jwilhelm@7174 88
jwilhelm@7174 89 private static final long initialHeapSize = getHeapMemoryUsage().getUsed();
jwilhelm@7174 90
jwilhelm@7174 91 public static void main(String[] args) throws InterruptedException {
jwilhelm@7174 92 new GCTest().test();
jwilhelm@7174 93 }
jwilhelm@7174 94
jwilhelm@7174 95 private void test() throws InterruptedException {
jwilhelm@7174 96 MemoryUsagePrinter.printMemoryUsage("init");
jwilhelm@7174 97
jwilhelm@7174 98 allocate();
jwilhelm@7174 99 System.gc();
jwilhelm@7174 100 MemoryUsage muFull = getHeapMemoryUsage();
jwilhelm@7174 101 MemoryUsagePrinter.printMemoryUsage("allocated");
jwilhelm@7174 102
jwilhelm@7174 103 free();
jwilhelm@7174 104 //Thread.sleep(1000); // sleep before measures due lags in JMX
jwilhelm@7174 105 MemoryUsage muFree = getHeapMemoryUsage();
jwilhelm@7174 106 MemoryUsagePrinter.printMemoryUsage("free");
jwilhelm@7174 107
jwilhelm@7174 108 assertLessThan(muFree.getCommitted(), muFull.getCommitted(), prepareMessageCommittedIsNotLess() );
jwilhelm@7174 109 }
jwilhelm@7174 110
jwilhelm@7174 111 private void allocate() {
jwilhelm@7174 112 System.out.format("Will allocate objects of small size = %s and humongous size = %s",
jwilhelm@7174 113 MemoryUsagePrinter.humanReadableByteCount(SMALL_OBJS_SIZE, false),
jwilhelm@7174 114 MemoryUsagePrinter.humanReadableByteCount(HUMONG_OBJS_SIZE, false)
jwilhelm@7174 115 );
jwilhelm@7174 116
jwilhelm@7174 117 for (int i = 0; i < ALLOCATE_COUNT; i++) {
jwilhelm@7174 118 ArrayList<byte[]> stuff = new ArrayList<>();
jwilhelm@7174 119 allocateList(stuff, SMALL_OBJS_COUNT / ALLOCATE_COUNT, SMALL_OBJS_SIZE);
jwilhelm@7174 120 garbage.add(stuff);
jwilhelm@7174 121
jwilhelm@7174 122 ArrayList<byte[]> humongousStuff = new ArrayList<>();
jwilhelm@7174 123 allocateList(humongousStuff, 4, HUMONG_OBJS_SIZE);
jwilhelm@7174 124 garbage.add(humongousStuff);
jwilhelm@7174 125 }
jwilhelm@7174 126 }
jwilhelm@7174 127
jwilhelm@7174 128 private void free() {
jwilhelm@7174 129 // do not free last one list
jwilhelm@7174 130 garbage.subList(0, garbage.size() - 1).clear();
jwilhelm@7174 131
jwilhelm@7174 132 // do not free last one element from last list
jwilhelm@7174 133 ArrayList stuff = garbage.get(garbage.size() - 1);
jwilhelm@7174 134 if (stuff.size() > 1) {
jwilhelm@7174 135 stuff.subList(0, stuff.size() - 1).clear();
jwilhelm@7174 136 }
jwilhelm@7174 137 System.gc();
jwilhelm@7174 138 }
jwilhelm@7174 139
jwilhelm@7174 140 private String prepareMessageCommittedIsNotLess() {
jwilhelm@7174 141 return String.format(
jwilhelm@7174 142 "committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n"
jwilhelm@7174 143 + "%s = %s%n%s = %s",
jwilhelm@7174 144 MIN_FREE_RATIO_FLAG_NAME,
jwilhelm@7174 145 ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(),
jwilhelm@7174 146 MAX_FREE_RATIO_FLAG_NAME,
jwilhelm@7174 147 ManagementFactoryHelper.getDiagnosticMXBean().getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue()
jwilhelm@7174 148 );
jwilhelm@7174 149 }
jwilhelm@7174 150
jwilhelm@7174 151 private static void allocateList(List garbage, int count, int size) {
jwilhelm@7174 152 for (int i = 0; i < count; i++) {
jwilhelm@7174 153 garbage.add(new byte[size]);
jwilhelm@7174 154 }
jwilhelm@7174 155 }
jwilhelm@7174 156 }
jwilhelm@7174 157
jwilhelm@7174 158 static MemoryUsage getHeapMemoryUsage() {
jwilhelm@7174 159 return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
jwilhelm@7174 160 }
jwilhelm@7174 161
jwilhelm@7174 162 /**
jwilhelm@7174 163 * Prints memory usage to standard output
jwilhelm@7174 164 */
jwilhelm@7174 165 static class MemoryUsagePrinter {
jwilhelm@7174 166
jwilhelm@7174 167 public static String humanReadableByteCount(long bytes, boolean si) {
jwilhelm@7174 168 int unit = si ? 1000 : 1024;
jwilhelm@7174 169 if (bytes < unit) {
jwilhelm@7174 170 return bytes + " B";
jwilhelm@7174 171 }
jwilhelm@7174 172 int exp = (int) (Math.log(bytes) / Math.log(unit));
jwilhelm@7174 173 String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
jwilhelm@7174 174 return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
jwilhelm@7174 175 }
jwilhelm@7174 176
jwilhelm@7174 177 public static void printMemoryUsage(String label) {
jwilhelm@7174 178 MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
jwilhelm@7174 179 float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
jwilhelm@7174 180 System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
jwilhelm@7174 181 label,
jwilhelm@7174 182 humanReadableByteCount(memusage.getInit(), false),
jwilhelm@7174 183 humanReadableByteCount(memusage.getUsed(), false),
jwilhelm@7174 184 humanReadableByteCount(memusage.getCommitted(), false),
jwilhelm@7174 185 freeratio * 100
jwilhelm@7174 186 );
jwilhelm@7174 187 }
jwilhelm@7174 188 }
jwilhelm@7174 189 }

mercurial