Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java
32284 views
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
*/
23
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;
41
42
public class TestShrinkAuxiliaryData {
43
44
private static final int REGION_SIZE = 1024 * 1024;
45
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
};
57
58
private final int hotCardTableSize;
59
60
protected TestShrinkAuxiliaryData(int hotCardTableSize) {
61
this.hotCardTableSize = hotCardTableSize;
62
}
63
64
protected void test() throws Exception {
65
ArrayList<String> vmOpts = new ArrayList();
66
Collections.addAll(vmOpts, initialOpts);
67
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
}
75
76
printTestInfo(maxCacheSize);
77
78
vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
79
vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
80
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
}
88
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());
94
95
performTest(vmOptsWithAlign);
96
}
97
}
98
99
private void performTest(List<String> opts) throws Exception {
100
ProcessBuilder pb
101
= ProcessTools.createJavaProcessBuilder(
102
opts.toArray(new String[opts.size()])
103
);
104
105
OutputAnalyzer output = new OutputAnalyzer(pb.start());
106
System.out.println(output.getStdout());
107
System.err.println(output.getStderr());
108
output.shouldHaveExitValue(0);
109
}
110
111
private void printTestInfo(int maxCacheSize) {
112
113
DecimalFormat grouped = new DecimalFormat("000,000");
114
DecimalFormatSymbols formatSymbols = grouped.getDecimalFormatSymbols();
115
formatSymbols.setGroupingSeparator(' ');
116
grouped.setDecimalFormatSymbols(formatSymbols);
117
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
}
134
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
}
147
148
long availablePointersCount = availableMemory / Unsafe.ADDRESS_SIZE;
149
return (63 - (int) Long.numberOfLeadingZeros(availablePointersCount));
150
}
151
152
static class ShrinkAuxiliaryDataTest {
153
154
public static void main(String[] args) throws IOException {
155
156
ShrinkAuxiliaryDataTest testCase = new ShrinkAuxiliaryDataTest();
157
158
if (!testCase.checkEnvApplicability()) {
159
return;
160
}
161
162
testCase.test();
163
}
164
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() {
173
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
}
186
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
}
195
196
return true;
197
}
198
199
class GarbageObject {
200
201
private final List<byte[]> payload = new ArrayList();
202
private final List<GarbageObject> ref = new LinkedList();
203
204
public GarbageObject(int size) {
205
payload.add(new byte[size]);
206
}
207
208
public void addRef(GarbageObject g) {
209
ref.add(g);
210
}
211
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
}
218
219
private final List<GarbageObject> garbage = new ArrayList();
220
221
public void test() throws IOException {
222
223
MemoryUsage muFull, muFree, muAuxDataFull, muAuxDataFree;
224
float auxFull, auxFree;
225
226
allocate();
227
link();
228
mutate();
229
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;
235
236
System.out.format("Full aux data ratio= %f, regions max= %d, used= %d\n",
237
auxFull, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
238
);
239
240
deallocate();
241
System.gc();
242
243
muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
244
muAuxDataFree = WhiteBox.getWhiteBox().g1AuxiliaryMemoryUsage();
245
246
numUsedRegions = WhiteBox.getWhiteBox().g1NumMaxRegions()
247
- WhiteBox.getWhiteBox().g1NumFreeRegions();
248
auxFree = (float)muAuxDataFree.getUsed() / numUsedRegions;
249
250
System.out.format("Free aux data ratio= %f, regions max= %d, used= %d\n",
251
auxFree, WhiteBox.getWhiteBox().g1NumMaxRegions(), numUsedRegions
252
);
253
254
Asserts.assertLessThanOrEqual(muFree.getCommitted(), muFull.getCommitted(),
255
String.format("heap decommit failed - full > free: %d > %d",
256
muFree.getCommitted(), muFull.getCommitted()
257
)
258
);
259
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());
263
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
}
273
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
}
283
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;
291
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);
297
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
}
305
306
private void mutate() {
307
for (int ig = 0; ig < garbage.size(); ig++) {
308
garbage.get(ig).mutate();
309
}
310
}
311
312
private void deallocate() {
313
garbage.clear();
314
System.gc();
315
}
316
317
static long getMemoryUsedByTest() {
318
return REGIONS_TO_ALLOCATE * REGION_SIZE;
319
}
320
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
}
326
327