Mercurial > hg > graal-jvmci-8
comparison test/stress/gc/TestStressRSetCoarsening.java @ 23625:89c75331f9b6
8134963: [Newtest] New stress test for changing the coarseness level of G1 remembered set
Reviewed-by: tschatzl, mchernov
author | dfazunen |
---|---|
date | Wed, 03 Feb 2016 19:13:31 +0300 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
23624:1b73e7d0cab5 | 23625:89c75331f9b6 |
---|---|
1 /* | |
2 * Copyright (c) 2016, 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 java.util.concurrent.TimeoutException; | |
25 import sun.hotspot.WhiteBox; | |
26 | |
27 /* | |
28 * @test TestStressRSetCoarsening.java | |
29 * @key stress | |
30 * @bug 8146984 8147087 | |
31 * @requires vm.gc=="G1" | vm.gc=="null" | |
32 * @requires os.maxMemory > 3G | |
33 * | |
34 * @summary Stress G1 Remembered Set by creating a lot of cross region links | |
35 * @library /testlibrary /testlibrary/whitebox | |
36 * @build sun.hotspot.WhiteBox | |
37 * @run main ClassFileInstaller sun.hotspot.WhiteBox | |
38 * sun.hotspot.WhiteBox$WhiteBoxPermission | |
39 * @run main/othervm/timeout=300 | |
40 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
41 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
42 * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 | |
43 * @run main/othervm/timeout=300 | |
44 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
45 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
46 * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 | |
47 * @run main/othervm/timeout=300 | |
48 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
49 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
50 * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 | |
51 * @run main/othervm/timeout=300 | |
52 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
53 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
54 * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 | |
55 * @run main/othervm/timeout=1800 | |
56 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
57 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
58 * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 | |
59 * @run main/othervm/timeout=1800 | |
60 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC | |
61 * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc | |
62 * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 | |
63 */ | |
64 | |
65 /** | |
66 * What the test does. | |
67 * Preparation stage: | |
68 * Fill out ~90% of the heap with objects, each object is an object array. | |
69 * If we want to allocate K objects per region, we calculate N to meet: | |
70 * sizeOf(Object[N]) ~= regionSize / K | |
71 * Stress stage: | |
72 * No more allocation, so no more GC. | |
73 * We will perform a number of iterations. On each iteration i, | |
74 * for each pair of regions Rx and Ry we will set c[i] references | |
75 * from Rx to Ry. If c[i] less than c[i-1] at the end of iteration | |
76 * concurrent mark cycle will be initiated (to recalculate remembered sets). | |
77 * As the result RSet will be growing up and down, up and down many times. | |
78 * | |
79 * The test expects: no crash and no timeouts. | |
80 * | |
81 * Test Parameters: | |
82 * args[0] - number of objects per Heap Region (1 - means humongous) | |
83 * args[1] - number of regions to refresh to provoke GC at the end of cycle. | |
84 * (0 - means no GC, i.e. no reading from RSet) | |
85 * args[2] - timeout in seconds (to stop execution to avoid jtreg timeout) | |
86 */ | |
87 public class TestStressRSetCoarsening { | |
88 | |
89 public static void main(String... args) throws InterruptedException { | |
90 if (args.length != 3) { | |
91 throw new IllegalArgumentException("Wrong number of arguments " + args.length); | |
92 } | |
93 int objectsPerRegion = Integer.parseInt(args[0]); // 1 means humongous | |
94 int regsToRefresh = Integer.parseInt(args[1]); // 0 means no regions to refresh at the end of cycle | |
95 int timeout = Integer.parseInt(args[2]); // in seconds, test should stop working eariler | |
96 new TestStressRSetCoarsening(objectsPerRegion, regsToRefresh, timeout).go(); | |
97 } | |
98 | |
99 private static final long KB = 1024; | |
100 private static final long MB = 1024 * KB; | |
101 | |
102 private static final WhiteBox WB = WhiteBox.getWhiteBox(); | |
103 | |
104 public final Object[][] storage; | |
105 | |
106 /** | |
107 * Number of objects per region. This is a test parameter. | |
108 */ | |
109 public final int K; | |
110 | |
111 /** | |
112 * Length of object array: sizeOf(Object[N]) ~= regionSize / K | |
113 * N will be calculated as function of K. | |
114 */ | |
115 public final int N; | |
116 | |
117 /** | |
118 * How many regions involved into testing. | |
119 * Will be calculated as heapFractionToAllocate * freeRegionCount. | |
120 */ | |
121 public final int regionCount; | |
122 | |
123 /** | |
124 * How much heap to use. | |
125 */ | |
126 public final float heapFractionToAllocate = 0.9f; | |
127 | |
128 /** | |
129 * How many regions to be refreshed at the end of cycle. | |
130 * This is a test parameter. | |
131 */ | |
132 public final int regsToRefresh; | |
133 | |
134 /** | |
135 * Initial time. | |
136 */ | |
137 public final long start; | |
138 | |
139 /** | |
140 * Time when the test should stop working. | |
141 */ | |
142 public final long finishAt; | |
143 | |
144 /** | |
145 * Does pre-calculation and allocate necessary objects. | |
146 * | |
147 * @param objPerRegions how many objects per G1 heap region | |
148 */ | |
149 TestStressRSetCoarsening(int objPerRegions, int regsToRefresh, int timeout) { | |
150 this.K = objPerRegions; | |
151 this.regsToRefresh = regsToRefresh; | |
152 this.start = System.currentTimeMillis(); | |
153 this.finishAt = start + timeout * 900; // 10% ahead of jtreg timeout | |
154 | |
155 long regionSize = WB.g1RegionSize(); | |
156 | |
157 // How many free regions | |
158 Runtime rt = Runtime.getRuntime(); | |
159 long used = rt.totalMemory() - rt.freeMemory(); | |
160 long totalFree = rt.maxMemory() - used; | |
161 regionCount = (int) ((totalFree / regionSize) * heapFractionToAllocate); | |
162 long toAllocate = regionCount * regionSize; | |
163 System.out.println("%% Test parameters"); | |
164 System.out.println("%% Objects per region : " + K); | |
165 System.out.println("%% Heap fraction to allocate : " + (int) (heapFractionToAllocate * 100) + "%"); | |
166 System.out.println("%% Regions to refresh to provoke GC: " + regsToRefresh); | |
167 | |
168 System.out.println("%% Memory"); | |
169 System.out.println("%% used : " + used / MB + "M"); | |
170 System.out.println("%% available : " + totalFree / MB + "M"); | |
171 System.out.println("%% to allocate : " + toAllocate / MB + "M"); | |
172 System.out.println("%% (in regs) : " + regionCount); | |
173 System.out.println("%% G1 Region Size: " + regionSize / MB + "M"); | |
174 | |
175 int refSize = WB.getHeapOopSize(); | |
176 | |
177 // Calculate N: K*sizeOf(Object[N]) ~= regionSize | |
178 // sizeOf(Object[N]) ~= (N+4)*refSize | |
179 // ==> | |
180 // N = regionSize / K / refSize - 4; | |
181 N = (int) ((regionSize / K) / refSize) - 5; | |
182 | |
183 /* | |
184 * -------------- | |
185 * region0 storage[0] = new Object[N] | |
186 * ... | |
187 * storage[K-1] = new Object[N] | |
188 * --------------- | |
189 * region1 storage[K] = new Object[N] | |
190 * ... | |
191 * storage[2*K - 1] = new Object[N] | |
192 * -------------- | |
193 * ... | |
194 * -------------- | |
195 * regionX storage[X*K] = new Object[N] | |
196 * ... | |
197 * storage[(X+1)*K -1] = new Object[N] | |
198 * where X = HeapFraction * TotalRegions | |
199 * ------------- | |
200 */ | |
201 System.out.println("%% Objects"); | |
202 System.out.println("%% N (array length) : " + N); | |
203 System.out.println("%% K (objects in regions): " + K); | |
204 System.out.println("%% Reference size : " + refSize); | |
205 System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); | |
206 | |
207 storage = new Object[regionCount * K][]; | |
208 for (int i = 0; i < storage.length; i++) { | |
209 storage[i] = new Object[N]; | |
210 } | |
211 } | |
212 | |
213 public void go() throws InterruptedException { | |
214 // threshold for sparce -> fine | |
215 final int FINE = WB.getIntxVMFlag("G1RSetSparseRegionEntries").intValue(); | |
216 | |
217 // threshold for fine -> coarse | |
218 final int COARSE = WB.getIntxVMFlag("G1RSetRegionEntries").intValue(); | |
219 | |
220 // regToRegRefCounts - array of reference counts from region to region | |
221 // at the the end of iteration. | |
222 // The number of test iterations is array length - 1. | |
223 // If c[i] > c[i-1] then during the iteration i more references will | |
224 // be created. | |
225 // If c[i] < c[i-1] then some referenes will be cleaned. | |
226 int[] regToRegRefCounts = {0, FINE / 2, 0, FINE, (FINE + COARSE) / 2, 0, | |
227 COARSE, COARSE + 10, FINE + 1, FINE / 2, 0}; | |
228 | |
229 // For progress tracking | |
230 int[] progress = new int[regToRegRefCounts.length]; | |
231 progress[0] = 0; | |
232 for (int i = 1; i < regToRegRefCounts.length; i++) { | |
233 progress[i] = progress[i - 1] + Math.abs(regToRegRefCounts[i] - regToRegRefCounts[i - 1]); | |
234 } | |
235 try { | |
236 for (int i = 1; i < regToRegRefCounts.length; i++) { | |
237 int pre = regToRegRefCounts[i - 1]; | |
238 int cur = regToRegRefCounts[i]; | |
239 float prog = ((float) progress[i - 1] / progress[progress.length - 1]); | |
240 | |
241 System.out.println("%% step " + i | |
242 + " out of " + (regToRegRefCounts.length - 1) | |
243 + " (~" + (int) (100 * prog) + "% done)"); | |
244 System.out.println("%% " + pre + " --> " + cur); | |
245 for (int to = 0; to < regionCount; to++) { | |
246 // Select a celebrity object that we will install references to. | |
247 // The celebrity will be referred from all other regions. | |
248 // If the number of references after should be less than they | |
249 // were before, select NULL. | |
250 Object celebrity = cur > pre ? storage[to * K] : null; | |
251 for (int from = 0; from < regionCount; from++) { | |
252 if (to == from) { | |
253 continue; // no need to refer to itself | |
254 } | |
255 | |
256 int step = cur > pre ? +1 : -1; | |
257 for (int rn = pre; rn != cur; rn += step) { | |
258 storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity; | |
259 if (System.currentTimeMillis() > finishAt) { | |
260 throw new TimeoutException(); | |
261 } | |
262 } | |
263 } | |
264 } | |
265 if (pre > cur) { | |
266 // Number of references went down. | |
267 // Need to provoke recalculation of RSet. | |
268 WB.g1StartConcMarkCycle(); | |
269 while (WB.g1InConcurrentMark()) { | |
270 Thread.sleep(1); | |
271 } | |
272 } | |
273 | |
274 // To force the use of rememebered set entries we need to provoke a GC. | |
275 // To induce some fragmentation, and some mixed GCs, we need | |
276 // to make a few objects unreachable. | |
277 for (int toClean = i * regsToRefresh; toClean < (i + 1) * regsToRefresh; toClean++) { | |
278 int to = toClean % regionCount; | |
279 // Need to remove all references from all regions to the region 'to' | |
280 for (int from = 0; from < regionCount; from++) { | |
281 if (to == from) { | |
282 continue; // no need to refer to itself | |
283 } | |
284 for (int rn = 0; rn <= cur; rn++) { | |
285 storage[getY(to, from, rn)][getX(to, from, rn)] = null; | |
286 } | |
287 } | |
288 // 'Refresh' storage elements for the region 'to' | |
289 // After that loop all 'old' objects in the region 'to' | |
290 // should become unreachable. | |
291 for (int k = 0; k < K; k++) { | |
292 storage[(to * K + k) % storage.length] = new Object[N]; | |
293 } | |
294 } | |
295 } | |
296 } catch (TimeoutException e) { | |
297 System.out.println("%% TIMEOUT!!!"); | |
298 } | |
299 long now = System.currentTimeMillis(); | |
300 System.out.println("%% Summary"); | |
301 System.out.println("%% Time spent : " + ((now - start) / 1000) + " seconds"); | |
302 System.out.println("%% Free memory left : " + Runtime.getRuntime().freeMemory() / KB + "K"); | |
303 System.out.println("%% Test passed"); | |
304 } | |
305 | |
306 /** | |
307 * Returns X index in the Storage of the reference #rn from the region | |
308 * 'from' to the region 'to'. | |
309 * | |
310 * @param to region # to refer to | |
311 * @param from region # to refer from | |
312 * @param rn number of reference | |
313 * | |
314 * @return X index in the range: [0 ... N-1] | |
315 */ | |
316 private int getX(int to, int from, int rn) { | |
317 return (rn * regionCount + to) % N; | |
318 } | |
319 | |
320 /** | |
321 * Returns Y index in the Storage of the reference #rn from the region | |
322 * 'from' to the region 'to'. | |
323 * | |
324 * @param to region # to refer to | |
325 * @param from region # to refer from | |
326 * @param rn number of reference | |
327 * | |
328 * @return Y index in the range: [0 ... K*regionCount -1] | |
329 */ | |
330 private int getY(int to, int from, int rn) { | |
331 return ((rn * regionCount + to) / N + from * K) % (regionCount * K); | |
332 } | |
333 } | |
334 |