8223837: Add -XX:MinHeapSize flag to set the minimum heap size
Reviewed-by: pliden, tschatzl
This commit is contained in:
parent
75e9d0a290
commit
2fded1c480
src/hotspot/share
gc/shared
gcArguments.cppgcArguments.hppgc_globals.hppgenArguments.cppjvmFlagConstraintsGC.cppjvmFlagConstraintsGC.hpp
runtime
test/hotspot/jtreg/gc/arguments
@ -33,8 +33,6 @@
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
size_t MinHeapSize = 0;
|
||||
|
||||
size_t HeapAlignment = 0;
|
||||
size_t SpaceAlignment = 0;
|
||||
|
||||
@ -122,7 +120,7 @@ void GCArguments::assert_size_info() {
|
||||
assert(MaxHeapSize >= MinHeapSize, "Ergonomics decided on incompatible minimum and maximum heap sizes");
|
||||
assert(InitialHeapSize >= MinHeapSize, "Ergonomics decided on incompatible initial and minimum heap sizes");
|
||||
assert(MaxHeapSize >= InitialHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
|
||||
assert(MaxHeapSize % HeapAlignment == 0, "MinHeapSize alignment");
|
||||
assert(MinHeapSize % HeapAlignment == 0, "MinHeapSize alignment");
|
||||
assert(InitialHeapSize % HeapAlignment == 0, "InitialHeapSize alignment");
|
||||
assert(MaxHeapSize % HeapAlignment == 0, "MaxHeapSize alignment");
|
||||
}
|
||||
@ -149,7 +147,7 @@ void GCArguments::initialize_heap_flags_and_sizes() {
|
||||
if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
|
||||
vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
|
||||
}
|
||||
if (MinHeapSize != 0 && MaxHeapSize < MinHeapSize) {
|
||||
if (FLAG_IS_CMDLINE(MinHeapSize) && MaxHeapSize < MinHeapSize) {
|
||||
vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
|
||||
}
|
||||
}
|
||||
@ -166,28 +164,28 @@ void GCArguments::initialize_heap_flags_and_sizes() {
|
||||
}
|
||||
|
||||
// User inputs from -Xmx and -Xms must be aligned
|
||||
MinHeapSize = align_up(MinHeapSize, HeapAlignment);
|
||||
size_t aligned_initial_heap_size = align_up(InitialHeapSize, HeapAlignment);
|
||||
size_t aligned_max_heap_size = align_up(MaxHeapSize, HeapAlignment);
|
||||
|
||||
// Write back to flags if the values changed
|
||||
if (aligned_initial_heap_size != InitialHeapSize) {
|
||||
FLAG_SET_ERGO(InitialHeapSize, aligned_initial_heap_size);
|
||||
if (!is_aligned(MinHeapSize, HeapAlignment)) {
|
||||
FLAG_SET_ERGO(MinHeapSize, align_up(MinHeapSize, HeapAlignment));
|
||||
}
|
||||
if (aligned_max_heap_size != MaxHeapSize) {
|
||||
FLAG_SET_ERGO(MaxHeapSize, aligned_max_heap_size);
|
||||
if (!is_aligned(InitialHeapSize, HeapAlignment)) {
|
||||
FLAG_SET_ERGO(InitialHeapSize, align_up(InitialHeapSize, HeapAlignment));
|
||||
}
|
||||
if (!is_aligned(MaxHeapSize, HeapAlignment)) {
|
||||
FLAG_SET_ERGO(MaxHeapSize, align_up(MaxHeapSize, HeapAlignment));
|
||||
}
|
||||
|
||||
if (FLAG_IS_CMDLINE(InitialHeapSize) && MinHeapSize != 0 &&
|
||||
if (FLAG_IS_CMDLINE(InitialHeapSize) && FLAG_IS_CMDLINE(MinHeapSize) &&
|
||||
InitialHeapSize < MinHeapSize) {
|
||||
vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
|
||||
}
|
||||
|
||||
if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
|
||||
FLAG_SET_ERGO(MaxHeapSize, InitialHeapSize);
|
||||
} else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
|
||||
FLAG_SET_ERGO(InitialHeapSize, MaxHeapSize);
|
||||
if (InitialHeapSize < MinHeapSize) {
|
||||
MinHeapSize = InitialHeapSize;
|
||||
FLAG_SET_ERGO(MinHeapSize, InitialHeapSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,6 @@
|
||||
|
||||
class CollectedHeap;
|
||||
|
||||
extern size_t MinHeapSize;
|
||||
|
||||
extern size_t HeapAlignment;
|
||||
extern size_t SpaceAlignment;
|
||||
|
||||
|
@ -713,6 +713,10 @@
|
||||
"to move") \
|
||||
\
|
||||
/* gc parameters */ \
|
||||
product(size_t, MinHeapSize, 0, \
|
||||
"Minimum heap size (in bytes); zero means use ergonomics") \
|
||||
constraint(MinHeapSizeConstraintFunc,AfterErgo) \
|
||||
\
|
||||
product(size_t, InitialHeapSize, 0, \
|
||||
"Initial heap size (in bytes); zero means use ergonomics") \
|
||||
constraint(InitialHeapSizeConstraintFunc,AfterErgo) \
|
||||
|
@ -90,7 +90,7 @@ void GenArguments::initialize_heap_flags_and_sizes() {
|
||||
}
|
||||
// If needed, synchronize MinHeapSize size and InitialHeapSize
|
||||
if (MinHeapSize < smallest_heap_size) {
|
||||
MinHeapSize = smallest_heap_size;
|
||||
FLAG_SET_ERGO(MinHeapSize, smallest_heap_size);
|
||||
if (InitialHeapSize < MinHeapSize) {
|
||||
FLAG_SET_ERGO(InitialHeapSize, smallest_heap_size);
|
||||
}
|
||||
|
@ -319,6 +319,10 @@ static JVMFlag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bo
|
||||
return MaxSizeForAlignment(name, value, heap_alignment, verbose);
|
||||
}
|
||||
|
||||
JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose) {
|
||||
return MaxSizeForHeapAlignment("MinHeapSize", value, verbose);
|
||||
}
|
||||
|
||||
JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
|
||||
return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ JVMFlag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose);
|
||||
JVMFlag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose);
|
||||
JVMFlag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose);
|
||||
JVMFlag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose);
|
||||
JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose);
|
||||
JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose);
|
||||
JVMFlag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose);
|
||||
JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose);
|
||||
|
@ -1630,8 +1630,8 @@ void Arguments::set_use_compressed_oops() {
|
||||
#ifdef _LP64
|
||||
// MaxHeapSize is not set up properly at this point, but
|
||||
// the only value that can override MaxHeapSize if we are
|
||||
// to use UseCompressedOops is InitialHeapSize.
|
||||
size_t max_heap_size = MAX2(MaxHeapSize, InitialHeapSize);
|
||||
// to use UseCompressedOops are InitialHeapSize and MinHeapSize.
|
||||
size_t max_heap_size = MAX3(MaxHeapSize, InitialHeapSize, MinHeapSize);
|
||||
|
||||
if (max_heap_size <= max_heap_for_compressed_oops()) {
|
||||
#if !defined(COMPILER1) || defined(TIERED)
|
||||
@ -1832,6 +1832,8 @@ void Arguments::set_heap_size() {
|
||||
// after call to limit_by_allocatable_memory because that
|
||||
// method might reduce the allocation size.
|
||||
reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
|
||||
} else if (!FLAG_IS_DEFAULT(MinHeapSize)) {
|
||||
reasonable_max = MAX2(reasonable_max, (julong)MinHeapSize);
|
||||
}
|
||||
|
||||
log_trace(gc, heap)(" Maximum heap size " SIZE_FORMAT, (size_t) reasonable_max);
|
||||
@ -1855,13 +1857,13 @@ void Arguments::set_heap_size() {
|
||||
|
||||
reasonable_initial = limit_by_allocatable_memory(reasonable_initial);
|
||||
|
||||
log_trace(gc, heap)(" Initial heap size " SIZE_FORMAT, (size_t)reasonable_initial);
|
||||
FLAG_SET_ERGO(InitialHeapSize, (size_t)reasonable_initial);
|
||||
log_trace(gc, heap)(" Initial heap size " SIZE_FORMAT, InitialHeapSize);
|
||||
}
|
||||
// If the minimum heap size has not been set (via -Xms),
|
||||
// If the minimum heap size has not been set (via -Xms or -XX:MinHeapSize),
|
||||
// synchronize with InitialHeapSize to avoid errors with the default value.
|
||||
if (MinHeapSize == 0) {
|
||||
MinHeapSize = MIN2((size_t)reasonable_minimum, InitialHeapSize);
|
||||
FLAG_SET_ERGO(MinHeapSize, MIN2((size_t)reasonable_minimum, InitialHeapSize));
|
||||
log_trace(gc, heap)(" Minimum heap size " SIZE_FORMAT, MinHeapSize);
|
||||
}
|
||||
}
|
||||
@ -1903,8 +1905,9 @@ jint Arguments::set_aggressive_heap_flags() {
|
||||
if (FLAG_SET_CMDLINE(InitialHeapSize, initHeapSize) != JVMFlag::SUCCESS) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
// Currently the minimum size and the initial heap sizes are the same.
|
||||
MinHeapSize = initHeapSize;
|
||||
if (FLAG_SET_CMDLINE(MinHeapSize, initHeapSize) != JVMFlag::SUCCESS) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(NewSize)) {
|
||||
// Make the young generation 3/8ths of the total heap.
|
||||
@ -2595,19 +2598,19 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
|
||||
}
|
||||
// -Xms
|
||||
} else if (match_option(option, "-Xms", &tail)) {
|
||||
julong long_initial_heap_size = 0;
|
||||
julong size = 0;
|
||||
// an initial heap size of 0 means automatically determine
|
||||
ArgsRange errcode = parse_memory_size(tail, &long_initial_heap_size, 0);
|
||||
ArgsRange errcode = parse_memory_size(tail, &size, 0);
|
||||
if (errcode != arg_in_range) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Invalid initial heap size: %s\n", option->optionString);
|
||||
describe_range_error(errcode);
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
MinHeapSize = (size_t)long_initial_heap_size;
|
||||
// Currently the minimum size and the initial heap sizes are the same.
|
||||
// Can be overridden with -XX:InitialHeapSize.
|
||||
if (FLAG_SET_CMDLINE(InitialHeapSize, (size_t)long_initial_heap_size) != JVMFlag::SUCCESS) {
|
||||
if (FLAG_SET_CMDLINE(MinHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
if (FLAG_SET_CMDLINE(InitialHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
// -Xmx
|
||||
|
@ -55,6 +55,8 @@ class TestMaxHeapSizeTools {
|
||||
checkValidMinInitialHeapCombinations(gcflag);
|
||||
checkInvalidInitialMaxHeapCombinations(gcflag);
|
||||
checkValidInitialMaxHeapCombinations(gcflag);
|
||||
checkInvalidMinMaxHeapCombinations(gcflag);
|
||||
checkValidMinMaxHeapCombinations(gcflag);
|
||||
}
|
||||
|
||||
public static void checkMinInitialErgonomics(String gcflag) throws Exception {
|
||||
@ -71,18 +73,33 @@ class TestMaxHeapSizeTools {
|
||||
|
||||
// -Xms is not set
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue }, values, smallValue, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue }, values, largeValue, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=0" }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1);
|
||||
// Some extra checks when both are set.
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, largeValue, largeValue);
|
||||
|
||||
// -Xms is set to zero
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue }, values, smallValue, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue }, values, largeValue, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=0" }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, largeValue, largeValue);
|
||||
|
||||
// -Xms is set to small value
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=" + smallValue }, values, smallValue, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=0" }, values, -1, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
|
||||
@ -90,6 +107,7 @@ class TestMaxHeapSizeTools {
|
||||
// -Xms is set to large value
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
|
||||
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:MinHeapSize=0" }, values, -1, largeValue);
|
||||
}
|
||||
|
||||
private static long align_up(long value, long alignment) {
|
||||
@ -116,6 +134,9 @@ class TestMaxHeapSizeTools {
|
||||
private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
|
||||
expectError(new String[] { gcflag, "-XX:InitialHeapSize=1023K", "-version" });
|
||||
expectError(new String[] { gcflag, "-Xms64M", "-XX:InitialHeapSize=32M", "-version" });
|
||||
expectError(new String[] { gcflag, "-XX:MinHeapSize=1023K", "-version" });
|
||||
expectError(new String[] { gcflag, "-Xms4M", "-XX:MinHeapSize=8M", "-version" });
|
||||
expectError(new String[] { gcflag, "-XX:MinHeapSize=8M -XX:InitialHeapSize=4m" });
|
||||
}
|
||||
|
||||
private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
|
||||
@ -123,8 +144,13 @@ class TestMaxHeapSizeTools {
|
||||
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms4M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-Xms4M", "-XX:InitialHeapSize=8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MinHeapSize=1024K", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MinHeapSize=8M", "-Xms4M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MinHeapSize=8M", "-Xms8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-Xms8M", "-XX:MinHeapSize=4M", "-version" });
|
||||
// the following is not an error as -Xms sets both minimal and initial heap size
|
||||
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-Xms8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MinHeapSize=4M", "-Xms8M", "-version" });
|
||||
}
|
||||
|
||||
private static void checkInvalidInitialMaxHeapCombinations(String gcflag) throws Exception {
|
||||
@ -133,6 +159,12 @@ class TestMaxHeapSizeTools {
|
||||
expectError(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" });
|
||||
}
|
||||
|
||||
private static void checkInvalidMinMaxHeapCombinations(String gcflag) throws Exception {
|
||||
expectError(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:MinHeapSize=8M", "-version" });
|
||||
expectError(new String[] { gcflag, "-XX:MinHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" });
|
||||
}
|
||||
|
||||
|
||||
private static void checkValidInitialMaxHeapCombinations(String gcflag) throws Exception {
|
||||
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:InitialHeapSize=4M", "-version" });
|
||||
@ -141,6 +173,14 @@ class TestMaxHeapSizeTools {
|
||||
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=0M", "-version" });
|
||||
}
|
||||
|
||||
private static void checkValidMinMaxHeapCombinations(String gcflag) throws Exception {
|
||||
expectValid(new String[] { gcflag, "-XX:MinHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:MinHeapSize=4M", "-version" });
|
||||
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:MinHeapSize=4M", "-version" });
|
||||
// a value of "0" for min heap size means auto-detect
|
||||
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:MinHeapSize=0M", "-version" });
|
||||
}
|
||||
|
||||
private static long valueAfter(String source, String match) {
|
||||
int start = source.indexOf(match) + match.length();
|
||||
String tail = source.substring(start).split(" ")[0];
|
||||
@ -294,4 +334,3 @@ class TestMaxHeapSizeTools {
|
||||
expect(flags, false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user