Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/test/stress/gc/TestStressRSetCoarsening.java
32285 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.util.concurrent.TimeoutException;24import sun.hotspot.WhiteBox;2526/*27* @test TestStressRSetCoarsening.java28* @key stress29* @bug 8146984 814708730* @requires vm.gc=="G1" | vm.gc=="null"31* @requires os.maxMemory > 3G32*33* @summary Stress G1 Remembered Set by creating a lot of cross region links34* @library /testlibrary /testlibrary/whitebox35* @build sun.hotspot.WhiteBox36* @run main ClassFileInstaller sun.hotspot.WhiteBox37* sun.hotspot.WhiteBox$WhiteBoxPermission38* @run main/othervm/timeout=30039* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC40* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc41* -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 30042* @run main/othervm/timeout=30043* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC44* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc45* -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 30046* @run main/othervm/timeout=30047* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC48* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc49* -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 30050* @run main/othervm/timeout=30051* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC52* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc53* -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 30054* @run main/othervm/timeout=180055* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC56* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc57* -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 180058* @run main/othervm/timeout=180059* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC60* -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc61* -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 180062*/6364/**65* What the test does.66* Preparation stage:67* Fill out ~90% of the heap with objects, each object is an object array.68* If we want to allocate K objects per region, we calculate N to meet:69* sizeOf(Object[N]) ~= regionSize / K70* Stress stage:71* No more allocation, so no more GC.72* We will perform a number of iterations. On each iteration i,73* for each pair of regions Rx and Ry we will set c[i] references74* from Rx to Ry. If c[i] less than c[i-1] at the end of iteration75* concurrent mark cycle will be initiated (to recalculate remembered sets).76* As the result RSet will be growing up and down, up and down many times.77*78* The test expects: no crash and no timeouts.79*80* Test Parameters:81* args[0] - number of objects per Heap Region (1 - means humongous)82* args[1] - number of regions to refresh to provoke GC at the end of cycle.83* (0 - means no GC, i.e. no reading from RSet)84* args[2] - timeout in seconds (to stop execution to avoid jtreg timeout)85*/86public class TestStressRSetCoarsening {8788public static void main(String... args) throws InterruptedException {89if (args.length != 3) {90throw new IllegalArgumentException("Wrong number of arguments " + args.length);91}92int objectsPerRegion = Integer.parseInt(args[0]); // 1 means humongous93int regsToRefresh = Integer.parseInt(args[1]); // 0 means no regions to refresh at the end of cycle94int timeout = Integer.parseInt(args[2]); // in seconds, test should stop working eariler95new TestStressRSetCoarsening(objectsPerRegion, regsToRefresh, timeout).go();96}9798private static final long KB = 1024;99private static final long MB = 1024 * KB;100101private static final WhiteBox WB = WhiteBox.getWhiteBox();102103public final Object[][] storage;104105/**106* Number of objects per region. This is a test parameter.107*/108public final int K;109110/**111* Length of object array: sizeOf(Object[N]) ~= regionSize / K112* N will be calculated as function of K.113*/114public final int N;115116/**117* How many regions involved into testing.118* Will be calculated as heapFractionToAllocate * freeRegionCount.119*/120public final int regionCount;121122/**123* How much heap to use.124*/125public final float heapFractionToAllocate = 0.9f;126127/**128* How many regions to be refreshed at the end of cycle.129* This is a test parameter.130*/131public final int regsToRefresh;132133/**134* Initial time.135*/136public final long start;137138/**139* Time when the test should stop working.140*/141public final long finishAt;142143/**144* Does pre-calculation and allocate necessary objects.145*146* @param objPerRegions how many objects per G1 heap region147*/148TestStressRSetCoarsening(int objPerRegions, int regsToRefresh, int timeout) {149this.K = objPerRegions;150this.regsToRefresh = regsToRefresh;151this.start = System.currentTimeMillis();152this.finishAt = start + timeout * 900; // 10% ahead of jtreg timeout153154long regionSize = WB.g1RegionSize();155156// How many free regions157Runtime rt = Runtime.getRuntime();158long used = rt.totalMemory() - rt.freeMemory();159long totalFree = rt.maxMemory() - used;160regionCount = (int) ((totalFree / regionSize) * heapFractionToAllocate);161long toAllocate = regionCount * regionSize;162System.out.println("%% Test parameters");163System.out.println("%% Objects per region : " + K);164System.out.println("%% Heap fraction to allocate : " + (int) (heapFractionToAllocate * 100) + "%");165System.out.println("%% Regions to refresh to provoke GC: " + regsToRefresh);166167System.out.println("%% Memory");168System.out.println("%% used : " + used / MB + "M");169System.out.println("%% available : " + totalFree / MB + "M");170System.out.println("%% to allocate : " + toAllocate / MB + "M");171System.out.println("%% (in regs) : " + regionCount);172System.out.println("%% G1 Region Size: " + regionSize / MB + "M");173174int refSize = WB.getHeapOopSize();175176// Calculate N: K*sizeOf(Object[N]) ~= regionSize177// sizeOf(Object[N]) ~= (N+4)*refSize178// ==>179// N = regionSize / K / refSize - 4;180N = (int) ((regionSize / K) / refSize) - 5;181182/*183* --------------184* region0 storage[0] = new Object[N]185* ...186* storage[K-1] = new Object[N]187* ---------------188* region1 storage[K] = new Object[N]189* ...190* storage[2*K - 1] = new Object[N]191* --------------192* ...193* --------------194* regionX storage[X*K] = new Object[N]195* ...196* storage[(X+1)*K -1] = new Object[N]197* where X = HeapFraction * TotalRegions198* -------------199*/200System.out.println("%% Objects");201System.out.println("%% N (array length) : " + N);202System.out.println("%% K (objects in regions): " + K);203System.out.println("%% Reference size : " + refSize);204System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)");205206storage = new Object[regionCount * K][];207for (int i = 0; i < storage.length; i++) {208storage[i] = new Object[N];209}210}211212public void go() throws InterruptedException {213// threshold for sparce -> fine214final int FINE = WB.getIntxVMFlag("G1RSetSparseRegionEntries").intValue();215216// threshold for fine -> coarse217final int COARSE = WB.getIntxVMFlag("G1RSetRegionEntries").intValue();218219// regToRegRefCounts - array of reference counts from region to region220// at the the end of iteration.221// The number of test iterations is array length - 1.222// If c[i] > c[i-1] then during the iteration i more references will223// be created.224// If c[i] < c[i-1] then some referenes will be cleaned.225int[] regToRegRefCounts = {0, FINE / 2, 0, FINE, (FINE + COARSE) / 2, 0,226COARSE, COARSE + 10, FINE + 1, FINE / 2, 0};227228// For progress tracking229int[] progress = new int[regToRegRefCounts.length];230progress[0] = 0;231for (int i = 1; i < regToRegRefCounts.length; i++) {232progress[i] = progress[i - 1] + Math.abs(regToRegRefCounts[i] - regToRegRefCounts[i - 1]);233}234try {235for (int i = 1; i < regToRegRefCounts.length; i++) {236int pre = regToRegRefCounts[i - 1];237int cur = regToRegRefCounts[i];238float prog = ((float) progress[i - 1] / progress[progress.length - 1]);239240System.out.println("%% step " + i241+ " out of " + (regToRegRefCounts.length - 1)242+ " (~" + (int) (100 * prog) + "% done)");243System.out.println("%% " + pre + " --> " + cur);244for (int to = 0; to < regionCount; to++) {245// Select a celebrity object that we will install references to.246// The celebrity will be referred from all other regions.247// If the number of references after should be less than they248// were before, select NULL.249Object celebrity = cur > pre ? storage[to * K] : null;250for (int from = 0; from < regionCount; from++) {251if (to == from) {252continue; // no need to refer to itself253}254255int step = cur > pre ? +1 : -1;256for (int rn = pre; rn != cur; rn += step) {257storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity;258if (System.currentTimeMillis() > finishAt) {259throw new TimeoutException();260}261}262}263}264if (pre > cur) {265// Number of references went down.266// Need to provoke recalculation of RSet.267WB.g1StartConcMarkCycle();268while (WB.g1InConcurrentMark()) {269Thread.sleep(1);270}271}272273// To force the use of rememebered set entries we need to provoke a GC.274// To induce some fragmentation, and some mixed GCs, we need275// to make a few objects unreachable.276for (int toClean = i * regsToRefresh; toClean < (i + 1) * regsToRefresh; toClean++) {277int to = toClean % regionCount;278// Need to remove all references from all regions to the region 'to'279for (int from = 0; from < regionCount; from++) {280if (to == from) {281continue; // no need to refer to itself282}283for (int rn = 0; rn <= cur; rn++) {284storage[getY(to, from, rn)][getX(to, from, rn)] = null;285}286}287// 'Refresh' storage elements for the region 'to'288// After that loop all 'old' objects in the region 'to'289// should become unreachable.290for (int k = 0; k < K; k++) {291storage[(to * K + k) % storage.length] = new Object[N];292}293}294}295} catch (TimeoutException e) {296System.out.println("%% TIMEOUT!!!");297}298long now = System.currentTimeMillis();299System.out.println("%% Summary");300System.out.println("%% Time spent : " + ((now - start) / 1000) + " seconds");301System.out.println("%% Free memory left : " + Runtime.getRuntime().freeMemory() / KB + "K");302System.out.println("%% Test passed");303}304305/**306* Returns X index in the Storage of the reference #rn from the region307* 'from' to the region 'to'.308*309* @param to region # to refer to310* @param from region # to refer from311* @param rn number of reference312*313* @return X index in the range: [0 ... N-1]314*/315private int getX(int to, int from, int rn) {316return (rn * regionCount + to) % N;317}318319/**320* Returns Y index in the Storage of the reference #rn from the region321* 'from' to the region 'to'.322*323* @param to region # to refer to324* @param from region # to refer from325* @param rn number of reference326*327* @return Y index in the range: [0 ... K*regionCount -1]328*/329private int getY(int to, int from, int rn) {330return ((rn * regionCount + to) / N + from * K) % (regionCount * K);331}332}333334335336