Mon, 06 Nov 2017 16:51:47 +0800
[Code Reorganization] remove trailing whitespace to pass jcheck test
tschatzl@7255 | 1 | /* |
azakharov@7835 | 2 | * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. |
tschatzl@7255 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
tschatzl@7255 | 4 | * |
tschatzl@7255 | 5 | * This code is free software; you can redistribute it and/or modify it |
tschatzl@7255 | 6 | * under the terms of the GNU General Public License version 2 only, as |
tschatzl@7255 | 7 | * published by the Free Software Foundation. |
tschatzl@7255 | 8 | * |
tschatzl@7255 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
tschatzl@7255 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
tschatzl@7255 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
tschatzl@7255 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
tschatzl@7255 | 13 | * accompanied this code). |
tschatzl@7255 | 14 | * |
tschatzl@7255 | 15 | * You should have received a copy of the GNU General Public License version |
tschatzl@7255 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
tschatzl@7255 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
tschatzl@7255 | 18 | * |
tschatzl@7255 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
tschatzl@7255 | 20 | * or visit www.oracle.com if you need additional information or have any |
tschatzl@7255 | 21 | * questions. |
tschatzl@7255 | 22 | */ |
tschatzl@7255 | 23 | |
azakharov@7835 | 24 | import com.oracle.java.testlibrary.Asserts; |
tschatzl@7255 | 25 | import com.oracle.java.testlibrary.OutputAnalyzer; |
tschatzl@7255 | 26 | import com.oracle.java.testlibrary.Platform; |
tschatzl@7255 | 27 | import com.oracle.java.testlibrary.ProcessTools; |
tschatzl@7255 | 28 | import com.oracle.java.testlibrary.Utils; |
tschatzl@7255 | 29 | import java.io.IOException; |
tschatzl@7255 | 30 | import java.lang.management.ManagementFactory; |
tschatzl@7255 | 31 | import java.lang.management.MemoryUsage; |
tschatzl@7255 | 32 | import java.text.DecimalFormat; |
tschatzl@7255 | 33 | import java.text.DecimalFormatSymbols; |
tschatzl@7255 | 34 | import java.util.ArrayList; |
tschatzl@7255 | 35 | import java.util.Arrays; |
tschatzl@7255 | 36 | import java.util.Collections; |
tschatzl@7255 | 37 | import java.util.LinkedList; |
tschatzl@7255 | 38 | import java.util.List; |
azakharov@7835 | 39 | import sun.misc.Unsafe; // for ADDRESS_SIZE |
azakharov@7835 | 40 | import sun.hotspot.WhiteBox; |
tschatzl@7255 | 41 | |
tschatzl@7255 | 42 | public class TestShrinkAuxiliaryData { |
tschatzl@7255 | 43 | |
azakharov@7835 | 44 | private static final int REGION_SIZE = 1024 * 1024; |
azakharov@7835 | 45 | |
tschatzl@7255 | 46 | private final static String[] initialOpts = new String[]{ |
tschatzl@7255 | 47 | "-XX:MinHeapFreeRatio=10", |
tschatzl@7255 | 48 | "-XX:MaxHeapFreeRatio=11", |
tschatzl@7255 | 49 | "-XX:+UseG1GC", |
azakharov@7835 | 50 | "-XX:G1HeapRegionSize=" + REGION_SIZE, |
azakharov@7337 | 51 | "-XX:-ExplicitGCInvokesConcurrent", |
azakharov@7835 | 52 | "-XX:+PrintGCDetails", |
azakharov@7835 | 53 | "-XX:+UnlockDiagnosticVMOptions", |
azakharov@7835 | 54 | "-XX:+WhiteBoxAPI", |
azakharov@7835 | 55 | "-Xbootclasspath/a:.", |
tschatzl@7255 | 56 | }; |
tschatzl@7255 | 57 | |
azakharov@7835 | 58 | private final int hotCardTableSize; |
tschatzl@7255 | 59 | |
azakharov@7835 | 60 | protected TestShrinkAuxiliaryData(int hotCardTableSize) { |
azakharov@7835 | 61 | this.hotCardTableSize = hotCardTableSize; |
tschatzl@7255 | 62 | } |
tschatzl@7255 | 63 | |
tschatzl@7255 | 64 | protected void test() throws Exception { |
tschatzl@7255 | 65 | ArrayList<String> vmOpts = new ArrayList(); |
tschatzl@7255 | 66 | Collections.addAll(vmOpts, initialOpts); |
tschatzl@7255 | 67 | |
tschatzl@7255 | 68 | int maxCacheSize = Math.max(0, Math.min(31, getMaxCacheSize())); |
azakharov@7835 | 69 | if (maxCacheSize < hotCardTableSize) { |
tschatzl@7255 | 70 | System.out.format("Skiping test for %d cache size due max cache size %d", |
azakharov@7835 | 71 | hotCardTableSize, maxCacheSize |
tschatzl@7255 | 72 | ); |
tschatzl@7255 | 73 | return; |
tschatzl@7255 | 74 | } |
tschatzl@7255 | 75 | |
tschatzl@7255 | 76 | printTestInfo(maxCacheSize); |
tschatzl@7255 | 77 | |
azakharov@7835 | 78 | vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize); |
jwilhelm@7785 | 79 | vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts())); |
tschatzl@7255 | 80 | |
tschatzl@7255 | 81 | // for 32 bits ObjectAlignmentInBytes is not a option |
tschatzl@7255 | 82 | if (Platform.is32bit()) { |
tschatzl@7255 | 83 | ArrayList<String> vmOptsWithoutAlign = new ArrayList(vmOpts); |
tschatzl@7255 | 84 | vmOptsWithoutAlign.add(ShrinkAuxiliaryDataTest.class.getName()); |
tschatzl@7255 | 85 | performTest(vmOptsWithoutAlign); |
tschatzl@7255 | 86 | return; |
tschatzl@7255 | 87 | } |
tschatzl@7255 | 88 | |
tschatzl@7255 | 89 | for (int alignment = 3; alignment <= 8; alignment++) { |
tschatzl@7255 | 90 | ArrayList<String> vmOptsWithAlign = new ArrayList(vmOpts); |
tschatzl@7255 | 91 | vmOptsWithAlign.add("-XX:ObjectAlignmentInBytes=" |
tschatzl@7255 | 92 | + (int) Math.pow(2, alignment)); |
tschatzl@7255 | 93 | vmOptsWithAlign.add(ShrinkAuxiliaryDataTest.class.getName()); |
tschatzl@7255 | 94 | |
tschatzl@7255 | 95 | performTest(vmOptsWithAlign); |
tschatzl@7255 | 96 | } |
tschatzl@7255 | 97 | } |
tschatzl@7255 | 98 | |
tschatzl@7255 | 99 | private void performTest(List<String> opts) throws Exception { |
tschatzl@7255 | 100 | ProcessBuilder pb |
azakharov@7835 | 101 | = ProcessTools.createJavaProcessBuilder( |
azakharov@7835 | 102 | opts.toArray(new String[opts.size()]) |
azakharov@7835 | 103 | ); |
tschatzl@7255 | 104 | |
tschatzl@7255 | 105 | OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
azakharov@7835 | 106 | System.out.println(output.getStdout()); |
azakharov@7835 | 107 | System.err.println(output.getStderr()); |
tschatzl@7255 | 108 | output.shouldHaveExitValue(0); |
tschatzl@7255 | 109 | } |
tschatzl@7255 | 110 | |
tschatzl@7255 | 111 | private void printTestInfo(int maxCacheSize) { |
tschatzl@7255 | 112 | |
tschatzl@7255 | 113 | DecimalFormat grouped = new DecimalFormat("000,000"); |
tschatzl@7255 | 114 | DecimalFormatSymbols formatSymbols = grouped.getDecimalFormatSymbols(); |
tschatzl@7255 | 115 | formatSymbols.setGroupingSeparator(' '); |
tschatzl@7255 | 116 | grouped.setDecimalFormatSymbols(formatSymbols); |
tschatzl@7255 | 117 | |
azakharov@7835 | 118 | System.out.format( |
azakharov@7835 | 119 | "Test will use %s bytes of memory of %s available%n" |
tschatzl@7255 | 120 | + "Available memory is %s with %d bytes pointer size - can save %s pointers%n" |
tschatzl@7255 | 121 | + "Max cache size: 2^%d = %s elements%n", |
tschatzl@7255 | 122 | grouped.format(ShrinkAuxiliaryDataTest.getMemoryUsedByTest()), |
azakharov@7835 | 123 | grouped.format(Runtime.getRuntime().maxMemory()), |
azakharov@7835 | 124 | grouped.format(Runtime.getRuntime().maxMemory() |
tschatzl@7255 | 125 | - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()), |
tschatzl@7255 | 126 | Unsafe.ADDRESS_SIZE, |
tschatzl@7255 | 127 | grouped.format((Runtime.getRuntime().freeMemory() |
tschatzl@7255 | 128 | - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()) |
tschatzl@7255 | 129 | / Unsafe.ADDRESS_SIZE), |
tschatzl@7255 | 130 | maxCacheSize, |
tschatzl@7255 | 131 | grouped.format((int) Math.pow(2, maxCacheSize)) |
tschatzl@7255 | 132 | ); |
tschatzl@7255 | 133 | } |
tschatzl@7255 | 134 | |
tschatzl@7255 | 135 | /** |
tschatzl@7255 | 136 | * Detects maximum possible size of G1ConcRSLogCacheSize available for |
tschatzl@7255 | 137 | * current process based on maximum available process memory size |
tschatzl@7255 | 138 | * |
tschatzl@7255 | 139 | * @return power of two |
tschatzl@7255 | 140 | */ |
tschatzl@7255 | 141 | private static int getMaxCacheSize() { |
tschatzl@7255 | 142 | long availableMemory = Runtime.getRuntime().freeMemory() |
tschatzl@7255 | 143 | - ShrinkAuxiliaryDataTest.getMemoryUsedByTest() - 1l; |
tschatzl@7255 | 144 | if (availableMemory <= 0) { |
tschatzl@7255 | 145 | return 0; |
tschatzl@7255 | 146 | } |
azakharov@7835 | 147 | |
tschatzl@7255 | 148 | long availablePointersCount = availableMemory / Unsafe.ADDRESS_SIZE; |
tschatzl@7255 | 149 | return (63 - (int) Long.numberOfLeadingZeros(availablePointersCount)); |
tschatzl@7255 | 150 | } |
tschatzl@7255 | 151 | |
tschatzl@7255 | 152 | static class ShrinkAuxiliaryDataTest { |
tschatzl@7255 | 153 | |
tschatzl@7255 | 154 | public static void main(String[] args) throws IOException { |
tschatzl@7255 | 155 | |
azakharov@7835 | 156 | ShrinkAuxiliaryDataTest testCase = new ShrinkAuxiliaryDataTest(); |
azakharov@7835 | 157 | |
azakharov@7835 | 158 | if (!testCase.checkEnvApplicability()) { |
azakharov@7835 | 159 | return; |
tschatzl@7255 | 160 | } |
tschatzl@7255 | 161 | |
azakharov@7835 | 162 | testCase.test(); |
azakharov@7835 | 163 | } |
azakharov@7835 | 164 | |
azakharov@7835 | 165 | /** |
azakharov@7835 | 166 | * Checks is this environment suitable to run this test |
azakharov@7835 | 167 | * - memory is enough to decommit (page size is not big) |
azakharov@7835 | 168 | * - RSet cache size is not too big |
azakharov@7835 | 169 | * |
azakharov@7835 | 170 | * @return true if test could run, false if test should be skipped |
azakharov@7835 | 171 | */ |
azakharov@7835 | 172 | protected boolean checkEnvApplicability() { |
azakharov@7835 | 173 | |
azakharov@7835 | 174 | int pageSize = WhiteBox.getWhiteBox().getVMPageSize(); |
azakharov@7835 | 175 | System.out.println( "Page size = " + pageSize |
azakharov@7835 | 176 | + " region size = " + REGION_SIZE |
azakharov@7835 | 177 | + " aux data ~= " + (REGION_SIZE * 3 / 100)); |
azakharov@7835 | 178 | // If auxdata size will be less than page size it wouldn't decommit. |
azakharov@7835 | 179 | // Auxiliary data size is about ~3.6% of heap size. |
azakharov@7835 | 180 | if (pageSize >= REGION_SIZE * 3 / 100) { |
azakharov@7835 | 181 | System.out.format("Skipping test for too large page size = %d", |
azakharov@7835 | 182 | pageSize |
azakharov@7835 | 183 | ); |
azakharov@7835 | 184 | return false; |
azakharov@7835 | 185 | } |
azakharov@7835 | 186 | |
azakharov@7835 | 187 | if (REGION_SIZE * REGIONS_TO_ALLOCATE > Runtime.getRuntime().maxMemory()) { |
azakharov@7835 | 188 | System.out.format("Skipping test for too low available memory. " |
azakharov@7835 | 189 | + "Need %d, available %d", |
azakharov@7835 | 190 | REGION_SIZE * REGIONS_TO_ALLOCATE, |
azakharov@7835 | 191 | Runtime.getRuntime().maxMemory() |
azakharov@7835 | 192 | ); |
azakharov@7835 | 193 | return false; |
azakharov@7835 | 194 | } |
azakharov@7835 | 195 | |
azakharov@7835 | 196 | return true; |
tschatzl@7255 | 197 | } |
tschatzl@7255 | 198 | |
tschatzl@7255 | 199 | class GarbageObject { |
tschatzl@7255 | 200 | |
tschatzl@7255 | 201 | private final List<byte[]> payload = new ArrayList(); |
tschatzl@7255 | 202 | private final List<GarbageObject> ref = new LinkedList(); |
tschatzl@7255 | 203 | |
tschatzl@7255 | 204 | public GarbageObject(int size) { |
tschatzl@7255 | 205 | payload.add(new byte[size]); |
tschatzl@7255 | 206 | } |
tschatzl@7255 | 207 | |
tschatzl@7255 | 208 | public void addRef(GarbageObject g) { |
tschatzl@7255 | 209 | ref.add(g); |
tschatzl@7255 | 210 | } |
tschatzl@7255 | 211 | |
tschatzl@7255 | 212 | public void mutate() { |
tschatzl@7255 | 213 | if (!payload.isEmpty() && payload.get(0).length > 0) { |
tschatzl@7255 | 214 | payload.get(0)[0] = (byte) (Math.random() * Byte.MAX_VALUE); |
tschatzl@7255 | 215 | } |
tschatzl@7255 | 216 | } |
tschatzl@7255 | 217 | } |
tschatzl@7255 | 218 | |
tschatzl@7255 | 219 | private final List<GarbageObject> garbage = new ArrayList(); |
tschatzl@7255 | 220 | |
azakharov@7835 | 221 | public void test() throws IOException { |
azakharov@7835 | 222 | |
azakharov@7835 | 223 | MemoryUsage muFull, muFree, muAuxDataFull, muAuxDataFree; |
azakharov@7835 | 224 | float auxFull, auxFree; |
tschatzl@7255 | 225 | |
tschatzl@7255 | 226 | allocate(); |
tschatzl@7255 | 227 | link(); |
tschatzl@7255 | 228 | mutate(); |
azakharov@7835 | 229 | |
azakharov@7835 | 230 | muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); |
azakharov@7835 | 231 | long numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions() |
azakharov@7835 | 232 | - WhiteBox.getWhiteBox().g1NumFreeRegions(); |
azakharov@7835 | 233 | muAuxDataFull = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage(); |
azakharov@7835 | 234 | auxFull = (float)muAuxDataFull.getUsed() / numUsedRegions; |
azakharov@7835 | 235 | |
azakharov@7835 | 236 | System.out.format("Full aux data ratio= %f, regions max= %d, used= %d\n", |
azakharov@7835 | 237 | auxFull, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions |
azakharov@7835 | 238 | ); |
azakharov@7835 | 239 | |
tschatzl@7255 | 240 | deallocate(); |
azakharov@7835 | 241 | System.gc(); |
tschatzl@7255 | 242 | |
azakharov@7835 | 243 | muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); |
azakharov@7835 | 244 | muAuxDataFree = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage(); |
tschatzl@7255 | 245 | |
azakharov@7835 | 246 | numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions() |
azakharov@7835 | 247 | - WhiteBox.getWhiteBox().g1NumFreeRegions(); |
azakharov@7835 | 248 | auxFree = (float)muAuxDataFree.getUsed() / numUsedRegions; |
tschatzl@7255 | 249 | |
azakharov@7835 | 250 | System.out.format("Free aux data ratio= %f, regions max= %d, used= %d\n", |
azakharov@7835 | 251 | auxFree, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions |
azakharov@7835 | 252 | ); |
tschatzl@7255 | 253 | |
azakharov@7835 | 254 | Asserts.assertLessThanOrEqual(muFree.getCommitted(), muFull.getCommitted(), |
azakharov@7835 | 255 | String.format("heap decommit failed - full > free: %d > %d", |
azakharov@7835 | 256 | muFree.getCommitted(), muFull.getCommitted() |
tschatzl@7255 | 257 | ) |
tschatzl@7255 | 258 | ); |
tschatzl@7255 | 259 | |
azakharov@7835 | 260 | System.out.format("State used committed\n"); |
azakharov@7835 | 261 | System.out.format("Full aux data: %10d %10d\n", muAuxDataFull.getUsed(), muAuxDataFull.getCommitted()); |
azakharov@7835 | 262 | System.out.format("Free aux data: %10d %10d\n", muAuxDataFree.getUsed(), muAuxDataFree.getCommitted()); |
azakharov@7835 | 263 | |
azakharov@7835 | 264 | // if decommited check that aux data has same ratio |
azakharov@7835 | 265 | if (muFree.getCommitted() < muFull.getCommitted()) { |
azakharov@7835 | 266 | Asserts.assertLessThanOrEqual(auxFree, auxFull, |
azakharov@7835 | 267 | String.format("auxiliary data decommit failed - full > free: %f > %f", |
azakharov@7835 | 268 | auxFree, auxFull |
tschatzl@7255 | 269 | ) |
tschatzl@7255 | 270 | ); |
tschatzl@7255 | 271 | } |
tschatzl@7255 | 272 | } |
tschatzl@7255 | 273 | |
tschatzl@7255 | 274 | private void allocate() { |
tschatzl@7255 | 275 | for (int r = 0; r < REGIONS_TO_ALLOCATE; r++) { |
tschatzl@7255 | 276 | for (int i = 0; i < NUM_OBJECTS_PER_REGION; i++) { |
tschatzl@7255 | 277 | GarbageObject g = new GarbageObject(REGION_SIZE |
tschatzl@7255 | 278 | / NUM_OBJECTS_PER_REGION); |
tschatzl@7255 | 279 | garbage.add(g); |
tschatzl@7255 | 280 | } |
tschatzl@7255 | 281 | } |
tschatzl@7255 | 282 | } |
tschatzl@7255 | 283 | |
tschatzl@7255 | 284 | /** |
tschatzl@7255 | 285 | * Iterate through all allocated objects, and link to objects in another |
tschatzl@7255 | 286 | * regions |
tschatzl@7255 | 287 | */ |
tschatzl@7255 | 288 | private void link() { |
tschatzl@7255 | 289 | for (int ig = 0; ig < garbage.size(); ig++) { |
tschatzl@7255 | 290 | int regionNumber = ig / NUM_OBJECTS_PER_REGION; |
tschatzl@7255 | 291 | |
tschatzl@7255 | 292 | for (int i = 0; i < NUM_LINKS; i++) { |
tschatzl@7255 | 293 | int regionToLink; |
tschatzl@7255 | 294 | do { |
azakharov@7835 | 295 | regionToLink = (int) (Math.random() * REGIONS_TO_ALLOCATE); |
tschatzl@7255 | 296 | } while (regionToLink == regionNumber); |
tschatzl@7255 | 297 | |
tschatzl@7255 | 298 | // get random garbage object from random region |
tschatzl@7255 | 299 | garbage.get(ig).addRef(garbage.get(regionToLink |
tschatzl@7255 | 300 | * NUM_OBJECTS_PER_REGION + (int) (Math.random() |
tschatzl@7255 | 301 | * NUM_OBJECTS_PER_REGION))); |
tschatzl@7255 | 302 | } |
tschatzl@7255 | 303 | } |
tschatzl@7255 | 304 | } |
tschatzl@7255 | 305 | |
tschatzl@7255 | 306 | private void mutate() { |
tschatzl@7255 | 307 | for (int ig = 0; ig < garbage.size(); ig++) { |
tschatzl@7255 | 308 | garbage.get(ig).mutate(); |
tschatzl@7255 | 309 | } |
tschatzl@7255 | 310 | } |
tschatzl@7255 | 311 | |
tschatzl@7255 | 312 | private void deallocate() { |
tschatzl@7255 | 313 | garbage.clear(); |
tschatzl@7255 | 314 | System.gc(); |
tschatzl@7255 | 315 | } |
tschatzl@7255 | 316 | |
tschatzl@7255 | 317 | static long getMemoryUsedByTest() { |
tschatzl@7255 | 318 | return REGIONS_TO_ALLOCATE * REGION_SIZE; |
tschatzl@7255 | 319 | } |
tschatzl@7255 | 320 | |
azakharov@7835 | 321 | private static final int REGIONS_TO_ALLOCATE = 100; |
tschatzl@7255 | 322 | private static final int NUM_OBJECTS_PER_REGION = 10; |
tschatzl@7255 | 323 | private static final int NUM_LINKS = 20; // how many links create for each object |
tschatzl@7255 | 324 | } |
tschatzl@7255 | 325 | } |