Merge
This commit is contained in:
commit
2c54bcb248
327
hotspot/test/gc/g1/plab/TestPLABPromotion.java
Normal file
327
hotspot/test/gc/g1/plab/TestPLABPromotion.java
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestPLABPromotion
|
||||
* @bug 8141278
|
||||
* @summary Test PLAB promotion
|
||||
* @requires vm.gc=="G1" | vm.gc=="null"
|
||||
* @library /testlibrary /../../test/lib /
|
||||
* @modules java.management
|
||||
* @build ClassFileInstaller
|
||||
* sun.hotspot.WhiteBox
|
||||
* gc.g1.plab.lib.MemoryConsumer
|
||||
* gc.g1.plab.lib.LogParser
|
||||
* gc.g1.plab.lib.AppPLABPromotion
|
||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run main gc.g1.plab.TestPLABPromotion
|
||||
*/
|
||||
package gc.g1.plab;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import gc.g1.plab.lib.AppPLABPromotion;
|
||||
import gc.g1.plab.lib.LogParser;
|
||||
import gc.g1.plab.lib.PLABUtils;
|
||||
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
/**
|
||||
* Test checks PLAB promotion of different size objects.
|
||||
*/
|
||||
public class TestPLABPromotion {
|
||||
|
||||
// GC ID with survivor PLAB statistics
|
||||
private final static long GC_ID_SURVIVOR_STATS = 1l;
|
||||
// GC ID with old PLAB statistics
|
||||
private final static long GC_ID_OLD_STATS = 2l;
|
||||
|
||||
// Threshold to determine whether the correct amount of objects were promoted.
|
||||
// This is only an approximate threshold for these checks.
|
||||
private final static long MEM_CONSUMPTION_THRESHOLD = 256l * 1024l;
|
||||
|
||||
private static final int PLAB_SIZE_SMALL = 1024;
|
||||
private static final int PLAB_SIZE_MEDIUM = 4096;
|
||||
private static final int PLAB_SIZE_HIGH = 65536;
|
||||
private static final int OBJECT_SIZE_SMALL = 10;
|
||||
private static final int OBJECT_SIZE_MEDIUM = 100;
|
||||
private static final int OBJECT_SIZE_HIGH = 1000;
|
||||
private static final int GC_NUM_SMALL = 1;
|
||||
private static final int GC_NUM_MEDIUM = 3;
|
||||
private static final int GC_NUM_HIGH = 7;
|
||||
private static final int WASTE_PCT_SMALL = 10;
|
||||
private static final int WASTE_PCT_MEDIUM = 20;
|
||||
private static final int WASTE_PCT_HIGH = 30;
|
||||
private static final int YOUNG_SIZE_LOW = 16;
|
||||
private static final int YOUNG_SIZE_HIGH = 64;
|
||||
private static final boolean PLAB_FIXED = true;
|
||||
private static final boolean PLAB_DYNAMIC = false;
|
||||
|
||||
private final static TestCase[] TEST_CASES = {
|
||||
// Test cases for unreachable object, PLAB size is fixed
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, false, false),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, false, false),
|
||||
// Test cases for reachable objects, PLAB size is fixed
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_MEDIUM, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, false),
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_HIGH, PLAB_FIXED, true, false),
|
||||
// Test cases for unreachable object, PLAB size is not fixed
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_LOW, PLAB_DYNAMIC, false, false),
|
||||
// Test cases for reachable objects, PLAB size is not fixed
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true),
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true),
|
||||
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, false),
|
||||
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true),
|
||||
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true)
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
for (TestCase testCase : TEST_CASES) {
|
||||
// What we going to check.
|
||||
testCase.print(System.out);
|
||||
List<String> options = PLABUtils.prepareOptions(testCase.toOptions());
|
||||
options.add(AppPLABPromotion.class.getName());
|
||||
OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()]));
|
||||
if (out.getExitValue() != 0) {
|
||||
System.out.println(out.getOutput());
|
||||
throw new RuntimeException("Expect exit code 0.");
|
||||
}
|
||||
checkResults(out.getOutput(), testCase);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkResults(String output, TestCase testCase) {
|
||||
long plabAllocatedSurvivor;
|
||||
long directAllocatedSurvivor;
|
||||
long plabAllocatedOld;
|
||||
long directAllocatedOld;
|
||||
long memAllocated = testCase.getMemToFill();
|
||||
long wordSize = Platform.is32bit() ? 4l : 8l;
|
||||
LogParser logParser = new LogParser(output);
|
||||
|
||||
Map<String, Long> survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS);
|
||||
Map<String, Long> oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS);
|
||||
|
||||
plabAllocatedSurvivor = wordSize * survivorStats.get("used");
|
||||
directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated");
|
||||
plabAllocatedOld = wordSize * oldStats.get("used");
|
||||
directAllocatedOld = wordSize * oldStats.get("direct_allocated");
|
||||
|
||||
System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated);
|
||||
System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated);
|
||||
|
||||
// Unreachable objects case
|
||||
if (testCase.isDeadObjectCase()) {
|
||||
// No dead objects should be promoted
|
||||
if (plabAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD || directAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Survivor");
|
||||
}
|
||||
if (plabAllocatedOld > MEM_CONSUMPTION_THRESHOLD || directAllocatedOld > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Old");
|
||||
}
|
||||
} else {
|
||||
// Live objects case
|
||||
if (testCase.isPromotedByPLAB()) {
|
||||
// All live small objects should be promoted using PLAB
|
||||
if (Math.abs(plabAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Expect that Survivor PLAB allocation are similar to all mem consumed");
|
||||
}
|
||||
if (Math.abs(plabAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Expect that Old PLAB allocation are similar to all mem consumed");
|
||||
}
|
||||
} else {
|
||||
// All big objects should be directly allocated
|
||||
if (Math.abs(directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test fails. Expect that Survivor direct allocation are similar to all mem consumed");
|
||||
}
|
||||
if (Math.abs(directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test fails. Expect that Old direct allocation are similar to all mem consumed");
|
||||
}
|
||||
}
|
||||
|
||||
// All promoted objects size should be similar to all consumed memory
|
||||
if (Math.abs(plabAllocatedSurvivor + directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test fails. Expect that Survivor gen total allocation are similar to all mem consumed");
|
||||
}
|
||||
if (Math.abs(plabAllocatedOld + directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test fails. Expect that Old gen total allocation are similar to all mem consumed");
|
||||
}
|
||||
}
|
||||
System.out.println("Test passed!");
|
||||
}
|
||||
|
||||
private static Map<String, Long> getPlabStats(LogParser logParser, LogParser.ReportType type, long gc_id) {
|
||||
|
||||
Map<String, Long> survivorStats = logParser.getEntries()
|
||||
.get(gc_id)
|
||||
.get(type);
|
||||
return survivorStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of one test case.
|
||||
*/
|
||||
private static class TestCase {
|
||||
|
||||
private final int wastePct;
|
||||
private final int plabSize;
|
||||
private final int chunkSize;
|
||||
private final int parGCThreads;
|
||||
private final int edenSize;
|
||||
private final boolean plabIsFixed;
|
||||
private final boolean objectsAreReachable;
|
||||
private final boolean promotedByPLAB;
|
||||
|
||||
/**
|
||||
* @param wastePct
|
||||
* ParallelGCBufferWastePct
|
||||
* @param plabSize
|
||||
* -XX:OldPLABSize and -XX:YoungPLABSize
|
||||
* @param chunkSize
|
||||
* requested object size for memory consumption
|
||||
* @param parGCThreads
|
||||
* -XX:ParallelGCThreads
|
||||
* @param edenSize
|
||||
* NewSize and MaxNewSize
|
||||
* @param plabIsFixed
|
||||
* Use dynamic PLAB or fixed size PLAB
|
||||
* @param objectsAreReachable
|
||||
* true - allocate live objects
|
||||
* false - allocate unreachable objects
|
||||
* @param promotedByPLAB
|
||||
* true - we expect to see PLAB allocation during promotion
|
||||
* false - objects will be directly allocated during promotion
|
||||
*/
|
||||
public TestCase(int wastePct,
|
||||
int plabSize,
|
||||
int chunkSize,
|
||||
int parGCThreads,
|
||||
int edenSize,
|
||||
boolean plabIsFixed,
|
||||
boolean objectsAreReachable,
|
||||
boolean promotedByPLAB
|
||||
) {
|
||||
if (wastePct == 0 || plabSize == 0 || chunkSize == 0 || parGCThreads == 0 || edenSize == 0) {
|
||||
throw new IllegalArgumentException("Parameters should not be 0");
|
||||
}
|
||||
this.wastePct = wastePct;
|
||||
this.plabSize = plabSize;
|
||||
this.chunkSize = chunkSize;
|
||||
this.parGCThreads = parGCThreads;
|
||||
this.edenSize = edenSize;
|
||||
this.plabIsFixed = plabIsFixed;
|
||||
this.objectsAreReachable = objectsAreReachable;
|
||||
this.promotedByPLAB = promotedByPLAB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert current TestCase to List of options.
|
||||
* Assume test will fill half of existed eden.
|
||||
*
|
||||
* @return
|
||||
* List of options
|
||||
*/
|
||||
public List<String> toOptions() {
|
||||
return Arrays.asList("-XX:ParallelGCThreads=" + parGCThreads,
|
||||
"-XX:ParallelGCBufferWastePct=" + wastePct,
|
||||
"-XX:OldPLABSize=" + plabSize,
|
||||
"-XX:YoungPLABSize=" + plabSize,
|
||||
"-XX:" + (plabIsFixed ? "-" : "+") + "ResizePLAB",
|
||||
"-Dchunk.size=" + chunkSize,
|
||||
"-Dreachable=" + objectsAreReachable,
|
||||
"-XX:NewSize=" + edenSize + "m",
|
||||
"-XX:MaxNewSize=" + edenSize + "m",
|
||||
"-Dmem.to.fill=" + getMemToFill()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print details about test case.
|
||||
*/
|
||||
public void print(PrintStream out) {
|
||||
boolean expectPLABAllocation = promotedByPLAB && objectsAreReachable;
|
||||
boolean expectDirectAllocation = (!promotedByPLAB) && objectsAreReachable;
|
||||
|
||||
out.println("Test case details:");
|
||||
out.println(" Young gen size : " + edenSize + "M");
|
||||
out.println(" Predefined PLAB size : " + plabSize);
|
||||
out.println(" Parallel GC buffer waste pct : " + wastePct);
|
||||
out.println(" Chunk size : " + chunkSize);
|
||||
out.println(" Parallel GC threads : " + parGCThreads);
|
||||
out.println(" Objects are created : " + (objectsAreReachable ? "reachable" : "unreachable"));
|
||||
out.println(" PLAB size is fixed: " + (plabIsFixed ? "yes" : "no"));
|
||||
out.println("Test expectations:");
|
||||
out.println(" PLAB allocation : " + (expectPLABAllocation ? "expected" : "unexpected"));
|
||||
out.println(" Direct allocation : " + (expectDirectAllocation ? "expected" : "unexpected"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* true if we expect PLAB allocation
|
||||
* false if no
|
||||
*/
|
||||
public boolean isPromotedByPLAB() {
|
||||
return promotedByPLAB;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* true if it is test case for unreachable objects
|
||||
* false for live objects
|
||||
*/
|
||||
public boolean isDeadObjectCase() {
|
||||
return !objectsAreReachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns amount of memory to fill
|
||||
*
|
||||
* @return amount of memory
|
||||
*/
|
||||
public long getMemToFill() {
|
||||
return (long) (edenSize) * 1024l * 1024l / 2;
|
||||
}
|
||||
}
|
||||
}
|
222
hotspot/test/gc/g1/plab/TestPLABResize.java
Normal file
222
hotspot/test/gc/g1/plab/TestPLABResize.java
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestPLABResize
|
||||
* @bug 8141278
|
||||
* @summary Test for PLAB resizing
|
||||
* @requires vm.gc=="G1" | vm.gc=="null"
|
||||
* @library /testlibrary /../../test/lib /
|
||||
* @modules java.management
|
||||
* @build ClassFileInstaller
|
||||
* sun.hotspot.WhiteBox
|
||||
* gc.g1.plab.lib.LogParser
|
||||
* gc.g1.plab.lib.MemoryConsumer
|
||||
* gc.g1.plab.lib.PLABUtils
|
||||
* gc.g1.plab.lib.AppPLABResize
|
||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run main gc.g1.plab.TestPLABResize
|
||||
*/
|
||||
package gc.g1.plab;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import gc.g1.plab.lib.LogParser;
|
||||
import gc.g1.plab.lib.PLABUtils;
|
||||
import gc.g1.plab.lib.AppPLABResize;
|
||||
|
||||
import jdk.test.lib.OutputAnalyzer;
|
||||
import jdk.test.lib.ProcessTools;
|
||||
|
||||
/**
|
||||
* Test for PLAB resizing.
|
||||
*/
|
||||
public class TestPLABResize {
|
||||
|
||||
private static final int OBJECT_SIZE_SMALL = 10;
|
||||
private static final int OBJECT_SIZE_MEDIUM = 70;
|
||||
private static final int OBJECT_SIZE_HIGH = 150;
|
||||
private static final int GC_NUM_SMALL = 1;
|
||||
private static final int GC_NUM_MEDIUM = 3;
|
||||
private static final int GC_NUM_HIGH = 7;
|
||||
private static final int WASTE_PCT_SMALL = 10;
|
||||
private static final int WASTE_PCT_MEDIUM = 20;
|
||||
private static final int WASTE_PCT_HIGH = 30;
|
||||
|
||||
private static final int ITERATIONS_SMALL = 3;
|
||||
private static final int ITERATIONS_MEDIUM = 5;
|
||||
private static final int ITERATIONS_HIGH = 8;
|
||||
|
||||
private final static TestCase[] TEST_CASES = {
|
||||
new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_SMALL, GC_NUM_SMALL, ITERATIONS_MEDIUM),
|
||||
new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_HIGH, ITERATIONS_SMALL),
|
||||
new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH),
|
||||
new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, ITERATIONS_MEDIUM),
|
||||
new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, ITERATIONS_SMALL),
|
||||
new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH),
|
||||
new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, ITERATIONS_MEDIUM),
|
||||
new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, ITERATIONS_SMALL),
|
||||
new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH)
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
for (TestCase testCase : TEST_CASES) {
|
||||
testCase.print(System.out);
|
||||
List<String> options = PLABUtils.prepareOptions(testCase.toOptions());
|
||||
options.add(AppPLABResize.class.getName());
|
||||
OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()]));
|
||||
if (out.getExitValue() != 0) {
|
||||
System.out.println(out.getOutput());
|
||||
throw new RuntimeException("Exit code is not 0");
|
||||
}
|
||||
checkResults(out.getOutput(), testCase);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks testing results.
|
||||
* Expected results - desired PLAB size is decreased and increased during promotion to Survivor.
|
||||
*
|
||||
* @param output - VM output
|
||||
* @param testCase
|
||||
*/
|
||||
private static void checkResults(String output, TestCase testCase) {
|
||||
final LogParser log = new LogParser(output);
|
||||
final Map<Long, Map<LogParser.ReportType, Map<String, Long>>> entries = log.getEntries();
|
||||
|
||||
final ArrayList<Long> plabSizes = entries.entrySet()
|
||||
.stream()
|
||||
.map(item -> {
|
||||
return item.getValue()
|
||||
.get(LogParser.ReportType.SURVIVOR_STATS)
|
||||
.get("desired_plab_sz");
|
||||
})
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// Check that desired plab size was changed during iterations.
|
||||
// It should decrease during first half of iterations
|
||||
// and increase after.
|
||||
List<Long> decreasedPlabs = plabSizes.subList(testCase.getIterations(), testCase.getIterations() * 2);
|
||||
List<Long> increasedPlabs = plabSizes.subList(testCase.getIterations() * 2, testCase.getIterations() * 3);
|
||||
|
||||
Long prev = decreasedPlabs.get(0);
|
||||
for (int index = 1; index < decreasedPlabs.size(); ++index) {
|
||||
Long current = decreasedPlabs.get(index);
|
||||
if (prev < current) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test failed! Expect that previous PLAB size should be greater than current. Prev.size: " + prev + " Current size:" + current);
|
||||
}
|
||||
prev = current;
|
||||
}
|
||||
|
||||
prev = increasedPlabs.get(0);
|
||||
for (int index = 1; index < increasedPlabs.size(); ++index) {
|
||||
Long current = increasedPlabs.get(index);
|
||||
if (prev > current) {
|
||||
System.out.println(output);
|
||||
throw new RuntimeException("Test failed! Expect that previous PLAB size should be less than current. Prev.size: " + prev + " Current size:" + current);
|
||||
}
|
||||
prev = current;
|
||||
}
|
||||
|
||||
System.out.println("Test passed!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of one test case.
|
||||
*/
|
||||
private static class TestCase {
|
||||
|
||||
private final int wastePct;
|
||||
private final int chunkSize;
|
||||
private final int parGCThreads;
|
||||
private final int iterations;
|
||||
|
||||
/**
|
||||
* @param wastePct
|
||||
* ParallelGCBufferWastePct
|
||||
* @param chunkSize
|
||||
* requested object size for memory consumption
|
||||
* @param parGCThreads
|
||||
* -XX:ParallelGCThreads
|
||||
* @param iterations
|
||||
*
|
||||
*/
|
||||
public TestCase(int wastePct,
|
||||
int chunkSize,
|
||||
int parGCThreads,
|
||||
int iterations
|
||||
) {
|
||||
if (wastePct == 0 || chunkSize == 0 || parGCThreads == 0 || iterations == 0) {
|
||||
throw new IllegalArgumentException("Parameters should not be 0");
|
||||
}
|
||||
this.wastePct = wastePct;
|
||||
|
||||
this.chunkSize = chunkSize;
|
||||
this.parGCThreads = parGCThreads;
|
||||
this.iterations = iterations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert current TestCase to List of options.
|
||||
*
|
||||
* @return
|
||||
* List of options
|
||||
*/
|
||||
public List<String> toOptions() {
|
||||
return Arrays.asList("-XX:ParallelGCThreads=" + parGCThreads,
|
||||
"-XX:ParallelGCBufferWastePct=" + wastePct,
|
||||
"-XX:+ResizePLAB",
|
||||
"-Dthreads=" + parGCThreads,
|
||||
"-Dchunk.size=" + chunkSize,
|
||||
"-Diterations=" + iterations,
|
||||
"-XX:NewSize=16m",
|
||||
"-XX:MaxNewSize=16m"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print details about test case.
|
||||
*/
|
||||
public void print(PrintStream out) {
|
||||
out.println("Test case details:");
|
||||
out.println(" Parallel GC buffer waste pct : " + wastePct);
|
||||
out.println(" Chunk size : " + chunkSize);
|
||||
out.println(" Parallel GC threads : " + parGCThreads);
|
||||
out.println(" Iterations: " + iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterations
|
||||
*/
|
||||
public int getIterations() {
|
||||
return iterations;
|
||||
}
|
||||
}
|
||||
}
|
85
hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java
Normal file
85
hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package gc.g1.plab.lib;
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
/**
|
||||
* This application is part of PLAB promotion test.
|
||||
* The application fills a part of young gen with a number of small objects.
|
||||
* Then it calls young GC twice to promote objects from eden to survivor, and from survivor to old.
|
||||
* The test which running the application is responsible to set up test parameters
|
||||
* and VM flags including flags turning GC logging on. The test will then check the produced log.
|
||||
*/
|
||||
final public class AppPLABPromotion {
|
||||
|
||||
private final static WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
|
||||
/**
|
||||
* AppPLABPromotion is used for testing PLAB promotion.
|
||||
* Expects the following properties to be set:
|
||||
* - chunk.size - size of one object (byte array)
|
||||
* - mem.to.fill - amount of memory to be consumed
|
||||
* - reachable - memory should be consumed by live or dead objects
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
long chunkSize = Long.getLong("chunk.size");
|
||||
long memToFill = Long.getLong("mem.to.fill");
|
||||
boolean reachable = Boolean.getBoolean("reachable");
|
||||
if (chunkSize == 0) {
|
||||
throw new IllegalArgumentException("Chunk size must be not 0");
|
||||
}
|
||||
if (memToFill <= 0) {
|
||||
throw new IllegalArgumentException("mem.to.fill property should be above 0");
|
||||
}
|
||||
// Fill requested amount of memory
|
||||
allocate(reachable, memToFill, chunkSize);
|
||||
// Promote all allocated objects from Eden to Survivor
|
||||
WHITE_BOX.youngGC();
|
||||
// Promote all allocated objects from Survivor to Old
|
||||
WHITE_BOX.youngGC();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param reachable - should allocate reachable object
|
||||
* @param memSize - Memory to fill
|
||||
* @param chunkSize - requested bytes per objects.
|
||||
* Actual size of bytes per object will be greater
|
||||
*/
|
||||
private static void allocate(boolean reachable, long memSize, long chunkSize) {
|
||||
long realSize = WHITE_BOX.getObjectSize(new byte[(int) chunkSize]);
|
||||
int items = (int) ((memSize - 1) / (realSize)) + 1;
|
||||
MemoryConsumer storage;
|
||||
if (reachable) {
|
||||
storage = new MemoryConsumer(items, (int) chunkSize);
|
||||
} else {
|
||||
storage = new MemoryConsumer(1, (int) chunkSize);
|
||||
}
|
||||
// Make all young gen available.
|
||||
WHITE_BOX.fullGC();
|
||||
storage.consume(items * chunkSize);
|
||||
}
|
||||
}
|
106
hotspot/test/gc/g1/plab/lib/AppPLABResize.java
Normal file
106
hotspot/test/gc/g1/plab/lib/AppPLABResize.java
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package gc.g1.plab.lib;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
/**
|
||||
* This application is part of PLAB Resize test.
|
||||
* The application allocates objects in 3 iterations:
|
||||
* 1. Objects of fixed size
|
||||
* 2. Objects of decreasing size
|
||||
* 3. Objects of increasing size
|
||||
* The application doesn't have any assumptions about expected behavior.
|
||||
* It's supposed to be executed by a test which should set up test parameters (object sizes, number of allocations, etc)
|
||||
* and VM flags including flags turning GC logging on. The test will then check the produced log.
|
||||
*
|
||||
* Expects the following properties to be set:
|
||||
* - iterations - amount of iteration per cycle.
|
||||
* - chunk.size - size of objects to be allocated
|
||||
* - threads - number of gc threads (-XX:ParallelGCThreads) to calculate PLAB sizes.
|
||||
*/
|
||||
final public class AppPLABResize {
|
||||
|
||||
// Memory to be promoted by PLAB for one thread.
|
||||
private static final long MEM_ALLOC_WORDS = 32768;
|
||||
// Defined by properties.
|
||||
private static final int ITERATIONS = Integer.getInteger("iterations");
|
||||
private static final long CHUNK = Long.getLong("chunk.size");
|
||||
private static final int GC_THREADS = Integer.getInteger("threads");
|
||||
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
|
||||
/**
|
||||
* Main method for AppPLABResizing. Application expect for next properties:
|
||||
* iterations, chunk.size and threads.
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
if (ITERATIONS == 0 || CHUNK == 0 || GC_THREADS == 0) {
|
||||
throw new IllegalArgumentException("Properties should be set");
|
||||
}
|
||||
|
||||
long wordSize = Platform.is32bit() ? 4l : 8l;
|
||||
// PLAB size is shared between threads.
|
||||
long initialMemorySize = wordSize * GC_THREADS * MEM_ALLOC_WORDS;
|
||||
|
||||
// Expect changing memory to half during all iterations.
|
||||
long memChangeStep = initialMemorySize / 2 / ITERATIONS;
|
||||
|
||||
WHITE_BOX.fullGC();
|
||||
|
||||
// Warm the PLAB. Fill memory ITERATIONS times without changing memory size.
|
||||
iterateAllocation(initialMemorySize, 0);
|
||||
// Fill memory ITERATIONS times.
|
||||
// Initial size is initialMemorySize and step is -memChangeStep
|
||||
iterateAllocation(initialMemorySize, -memChangeStep);
|
||||
// Fill memory ITERATIONS times.
|
||||
// Initial size is memoryAfterChanging, step is memChangeStep.
|
||||
// Memory size at start should be greater then last size on previous step.
|
||||
// Last size on previous step is initialMemorySize - memChangeStep*(ITERATIONS - 1)
|
||||
long memoryAfterChanging = initialMemorySize - memChangeStep * (ITERATIONS - 2);
|
||||
iterateAllocation(memoryAfterChanging, memChangeStep);
|
||||
}
|
||||
|
||||
private static void iterateAllocation(long memoryToFill, long change) {
|
||||
int items;
|
||||
if (change > 0) {
|
||||
items = (int) ((memoryToFill + change * ITERATIONS) / CHUNK) + 1;
|
||||
} else {
|
||||
items = (int) (memoryToFill / CHUNK) + 1;
|
||||
}
|
||||
|
||||
long currentMemToFill = memoryToFill;
|
||||
for (int iteration = 0; iteration < ITERATIONS; ++iteration) {
|
||||
MemoryConsumer storage = new MemoryConsumer(items, (int) CHUNK);
|
||||
storage.consume(currentMemToFill);
|
||||
// Promote all objects to survivor
|
||||
WHITE_BOX.youngGC();
|
||||
storage.clear();
|
||||
currentMemToFill += change;
|
||||
}
|
||||
}
|
||||
}
|
142
hotspot/test/gc/g1/plab/lib/LogParser.java
Normal file
142
hotspot/test/gc/g1/plab/lib/LogParser.java
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package gc.g1.plab.lib;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* LogParser class parses VM output to get PLAB and ConsumptionStats values.
|
||||
*
|
||||
* Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like:
|
||||
*
|
||||
* [2,244s][info ][gc ] GC(30) Concurrent Mark abort
|
||||
* [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
|
||||
* [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
|
||||
* [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms
|
||||
* [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
|
||||
* [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
|
||||
* [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms
|
||||
|
||||
*/
|
||||
final public class LogParser {
|
||||
|
||||
// Name for GC ID field in report.
|
||||
public final static String GC_ID = "gc_id";
|
||||
|
||||
/**
|
||||
* Type of parsed log element.
|
||||
*/
|
||||
public static enum ReportType {
|
||||
|
||||
SURVIVOR_STATS,
|
||||
OLD_STATS
|
||||
}
|
||||
|
||||
private final String log;
|
||||
|
||||
private final Map<Long, Map<ReportType, Map<String,Long>>> reportHolder;
|
||||
|
||||
// GC ID
|
||||
private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)");
|
||||
// Pattern for extraction pair <name>=<numeric value>
|
||||
private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+");
|
||||
|
||||
/**
|
||||
* Construct LogParser Object
|
||||
*
|
||||
* @param log - VM Output
|
||||
*/
|
||||
public LogParser(String log) {
|
||||
if (log == null) {
|
||||
throw new IllegalArgumentException("Parameter log should not be null.");
|
||||
}
|
||||
this.log = log;
|
||||
reportHolder = parseLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return log which is being processed
|
||||
*/
|
||||
public String getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of log entries.
|
||||
*
|
||||
* @return list of Pair with ReportType and Map of parameters/values.
|
||||
*/
|
||||
public Map<Long,Map<ReportType, Map<String,Long>>> getEntries() {
|
||||
return reportHolder;
|
||||
}
|
||||
|
||||
private Map<Long,Map<ReportType, Map<String,Long>>> parseLines() throws NumberFormatException {
|
||||
Scanner lineScanner = new Scanner(log);
|
||||
Map<Long,Map<ReportType, Map<String,Long>>> allocationStatistics = new HashMap<>();
|
||||
Optional<Long> gc_id;
|
||||
while (lineScanner.hasNextLine()) {
|
||||
String line = lineScanner.nextLine();
|
||||
gc_id = getGcId(line);
|
||||
if ( gc_id.isPresent() ) {
|
||||
Matcher matcher = PAIRS_PATTERN.matcher(line);
|
||||
if (matcher.find()) {
|
||||
Map<ReportType,Map<String, Long>> oneReportItem;
|
||||
ReportType reportType;
|
||||
// Second line in log is statistics for Old PLAB allocation
|
||||
if ( !allocationStatistics.containsKey(gc_id.get()) ) {
|
||||
oneReportItem = new EnumMap<>(ReportType.class);
|
||||
reportType = ReportType.SURVIVOR_STATS;
|
||||
allocationStatistics.put(gc_id.get(), oneReportItem);
|
||||
} else {
|
||||
oneReportItem = allocationStatistics.get(gc_id.get());
|
||||
reportType = ReportType.OLD_STATS;
|
||||
}
|
||||
|
||||
// Extract all pairs from log.
|
||||
HashMap<String, Long> plabStats = new HashMap<>();
|
||||
do {
|
||||
String pair = matcher.group();
|
||||
String[] nameValue = pair.replaceAll(" ", "").split("=");
|
||||
plabStats.put(nameValue[0], Long.parseLong(nameValue[1]));
|
||||
} while (matcher.find());
|
||||
oneReportItem.put(reportType,plabStats);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allocationStatistics;
|
||||
}
|
||||
|
||||
private Optional<Long> getGcId(String line) {
|
||||
Matcher number = GC_ID_PATTERN.matcher(line);
|
||||
if (number.find()) {
|
||||
return Optional.of(Long.parseLong(number.group(1)));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
86
hotspot/test/gc/g1/plab/lib/MemoryConsumer.java
Normal file
86
hotspot/test/gc/g1/plab/lib/MemoryConsumer.java
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package gc.g1.plab.lib;
|
||||
|
||||
/**
|
||||
* The MemoryConsumer is used for consuming different amount of memory.
|
||||
* Class will store not more than 'capacity' number of objects with 'chunk' size.
|
||||
* If we exceed capacity, object will be stored at existing entries,
|
||||
* all previously added objects will be overwritten.
|
||||
* If capacity=1, only last object will be saved.
|
||||
*/
|
||||
public class MemoryConsumer {
|
||||
|
||||
private int capacity;
|
||||
private int chunk;
|
||||
|
||||
private Object[] array;
|
||||
private int index;
|
||||
|
||||
/**
|
||||
* Create MemoryConsumer object with defined capacity
|
||||
*
|
||||
* @param capacity
|
||||
* @param chunk
|
||||
*/
|
||||
public MemoryConsumer(int capacity, int chunk) {
|
||||
if (capacity <= 0) {
|
||||
throw new IllegalArgumentException("Items number should be greater than 0.");
|
||||
}
|
||||
if (chunk <= 0) {
|
||||
throw new IllegalArgumentException("Chunk size should be greater than 0.");
|
||||
}
|
||||
this.capacity = capacity;
|
||||
this.chunk = chunk;
|
||||
index = 0;
|
||||
array = new Object[this.capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store object into MemoryConsumer.
|
||||
*
|
||||
* @param o - Object to store
|
||||
*/
|
||||
private void store(Object o) {
|
||||
if (array == null) {
|
||||
throw new RuntimeException("Capacity should be set before storing");
|
||||
}
|
||||
array[index % capacity] = o;
|
||||
++index;
|
||||
}
|
||||
|
||||
public void consume(long memoryToFill) {
|
||||
long allocated = 0;
|
||||
while (allocated < memoryToFill) {
|
||||
store(new byte[chunk]);
|
||||
allocated += chunk;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all stored objects.
|
||||
*/
|
||||
public void clear() {
|
||||
array = null;
|
||||
}
|
||||
}
|
83
hotspot/test/gc/g1/plab/lib/PLABUtils.java
Normal file
83
hotspot/test/gc/g1/plab/lib/PLABUtils.java
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package gc.g1.plab.lib;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
/**
|
||||
* Utilities for PLAB testing.
|
||||
*/
|
||||
public class PLABUtils {
|
||||
|
||||
/**
|
||||
* PLAB tests default options list
|
||||
*/
|
||||
private final static String[] GC_TUNE_OPTIONS = {
|
||||
"-XX:+UseG1GC",
|
||||
"-XX:G1HeapRegionSize=1m",
|
||||
"-XX:OldSize=64m",
|
||||
"-XX:-UseAdaptiveSizePolicy",
|
||||
"-XX:-UseTLAB",
|
||||
"-XX:SurvivorRatio=1"
|
||||
};
|
||||
|
||||
/**
|
||||
* GC logging options list.
|
||||
*/
|
||||
private final static String G1_PLAB_LOGGING_OPTIONS[] = {
|
||||
"-Xlog:gc=debug,gc+plab=debug"
|
||||
};
|
||||
|
||||
/**
|
||||
* List of options required to use WhiteBox.
|
||||
*/
|
||||
private final static String WB_DIAGNOSTIC_OPTIONS[] = {
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI"
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepares options for testing.
|
||||
*
|
||||
* @param options - additional options for testing
|
||||
* @return List of options
|
||||
*/
|
||||
public static List<String> prepareOptions(List<String> options) {
|
||||
if (options == null) {
|
||||
throw new IllegalArgumentException("Options cannot be null");
|
||||
}
|
||||
List<String> executionOtions = new ArrayList<>(
|
||||
Arrays.asList(Utils.getTestJavaOpts())
|
||||
);
|
||||
Collections.addAll(executionOtions, WB_DIAGNOSTIC_OPTIONS);
|
||||
Collections.addAll(executionOtions, G1_PLAB_LOGGING_OPTIONS);
|
||||
Collections.addAll(executionOtions, GC_TUNE_OPTIONS);
|
||||
executionOtions.addAll(options);
|
||||
return executionOtions;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user