Mon, 06 Nov 2017 16:51:47 +0800
[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 }