mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-29 00:02:34 +00:00
8382616: Create GCArguments::set_heap_size interface
Reviewed-by: jsikstro, ayang
This commit is contained in:
parent
64779a2541
commit
02c1fdeaef
@ -25,10 +25,12 @@
|
||||
|
||||
#include "gc/shared/cardTable.hpp"
|
||||
#include "gc/shared/gcArguments.hpp"
|
||||
#include "gc/shared/genArguments.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/formatBuffer.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
@ -56,6 +58,141 @@ void GCArguments::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t GCArguments::limit_heap_by_allocatable_memory(size_t limit) {
|
||||
// Limits the given heap size by the maximum amount of virtual
|
||||
// memory this process is currently allowed to use. It also takes
|
||||
// the virtual-to-physical ratio of the current GC into account.
|
||||
size_t fraction = MaxVirtMemFraction * heap_virtual_to_physical_ratio();
|
||||
size_t max_allocatable = os::commit_memory_limit();
|
||||
|
||||
return MIN2(limit, max_allocatable / fraction);
|
||||
}
|
||||
|
||||
// Use static initialization to get the default before parsing
|
||||
static const size_t DefaultHeapBaseMinAddress = HeapBaseMinAddress;
|
||||
|
||||
static size_t clamp_by_size_t_max(uint64_t value) {
|
||||
return (size_t)MIN2(value, (uint64_t)std::numeric_limits<size_t>::max());
|
||||
}
|
||||
|
||||
void GCArguments::set_heap_size() {
|
||||
// Check if the user has configured any limit on the amount of RAM we may use.
|
||||
bool has_ram_limit = !FLAG_IS_DEFAULT(MaxRAMPercentage) ||
|
||||
!FLAG_IS_DEFAULT(MinRAMPercentage) ||
|
||||
!FLAG_IS_DEFAULT(InitialRAMPercentage);
|
||||
|
||||
const physical_memory_size_type avail_mem = os::physical_memory();
|
||||
|
||||
// If the maximum heap size has not been set with -Xmx, then set it as
|
||||
// fraction of the size of physical memory, respecting the maximum and
|
||||
// minimum sizes of the heap.
|
||||
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
|
||||
uint64_t min_memory = (uint64_t)(((double)avail_mem * MinRAMPercentage) / 100);
|
||||
uint64_t max_memory = (uint64_t)(((double)avail_mem * MaxRAMPercentage) / 100);
|
||||
|
||||
const size_t reasonable_min = clamp_by_size_t_max(min_memory);
|
||||
size_t reasonable_max = clamp_by_size_t_max(max_memory);
|
||||
|
||||
if (reasonable_min < MaxHeapSize) {
|
||||
// Small physical memory, so use a minimum fraction of it for the heap
|
||||
reasonable_max = reasonable_min;
|
||||
} else {
|
||||
// Not-small physical memory, so require a heap at least
|
||||
// as large as MaxHeapSize
|
||||
reasonable_max = MAX2(reasonable_max, MaxHeapSize);
|
||||
}
|
||||
|
||||
if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
|
||||
// Limit the heap size to ErgoHeapSizeLimit
|
||||
reasonable_max = MIN2(reasonable_max, ErgoHeapSizeLimit);
|
||||
}
|
||||
|
||||
reasonable_max = limit_heap_by_allocatable_memory(reasonable_max);
|
||||
|
||||
if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
|
||||
// An initial heap size was specified on the command line,
|
||||
// so be sure that the maximum size is consistent. Done
|
||||
// after call to limit_heap_by_allocatable_memory because that
|
||||
// method might reduce the allocation size.
|
||||
reasonable_max = MAX2(reasonable_max, InitialHeapSize);
|
||||
} else if (!FLAG_IS_DEFAULT(MinHeapSize)) {
|
||||
reasonable_max = MAX2(reasonable_max, MinHeapSize);
|
||||
}
|
||||
|
||||
#ifdef _LP64
|
||||
if (UseCompressedOops) {
|
||||
// HeapBaseMinAddress can be greater than default but not less than.
|
||||
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
|
||||
if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) {
|
||||
// matches compressed oops printing flags
|
||||
log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least %zu "
|
||||
"(%zuG) which is greater than value given %zu",
|
||||
DefaultHeapBaseMinAddress,
|
||||
DefaultHeapBaseMinAddress/G,
|
||||
HeapBaseMinAddress);
|
||||
FLAG_SET_ERGO(HeapBaseMinAddress, DefaultHeapBaseMinAddress);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t heap_end = HeapBaseMinAddress + MaxHeapSize;
|
||||
uintptr_t max_coop_heap = Arguments::max_heap_for_compressed_oops();
|
||||
|
||||
// Limit the heap size to the maximum possible when using compressed oops
|
||||
if (heap_end < max_coop_heap) {
|
||||
// Heap should be above HeapBaseMinAddress to get zero based compressed
|
||||
// oops but it should be not less than default MaxHeapSize.
|
||||
max_coop_heap -= HeapBaseMinAddress;
|
||||
}
|
||||
|
||||
// If the user has configured any limit on the amount of RAM we may use,
|
||||
// then disable compressed oops if the calculated max exceeds max_coop_heap
|
||||
// and UseCompressedOops was not specified.
|
||||
if (reasonable_max > max_coop_heap) {
|
||||
if (FLAG_IS_ERGO(UseCompressedOops) && has_ram_limit) {
|
||||
log_debug(gc, heap, coops)("UseCompressedOops disabled due to "
|
||||
"max heap %zu > compressed oop heap %zu. "
|
||||
"Please check the setting of MaxRAMPercentage %5.2f.",
|
||||
reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage);
|
||||
FLAG_SET_ERGO(UseCompressedOops, false);
|
||||
} else {
|
||||
reasonable_max = max_coop_heap;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _LP64
|
||||
|
||||
log_trace(gc, heap)(" Maximum heap size %zu", reasonable_max);
|
||||
FLAG_SET_ERGO(MaxHeapSize, reasonable_max);
|
||||
}
|
||||
|
||||
// If the minimum or initial heap_size have not been set or requested to be set
|
||||
// ergonomically, set them accordingly.
|
||||
if (InitialHeapSize == 0 || MinHeapSize == 0) {
|
||||
size_t reasonable_minimum = clamp_by_size_t_max((uint64_t)OldSize + (uint64_t)NewSize);
|
||||
reasonable_minimum = MIN2(reasonable_minimum, MaxHeapSize);
|
||||
reasonable_minimum = limit_heap_by_allocatable_memory(reasonable_minimum);
|
||||
|
||||
if (InitialHeapSize == 0) {
|
||||
uint64_t initial_memory = (uint64_t)(((double)avail_mem * InitialRAMPercentage) / 100);
|
||||
size_t reasonable_initial = clamp_by_size_t_max(initial_memory);
|
||||
reasonable_initial = limit_heap_by_allocatable_memory(reasonable_initial);
|
||||
|
||||
reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, MinHeapSize);
|
||||
reasonable_initial = MIN2(reasonable_initial, MaxHeapSize);
|
||||
|
||||
FLAG_SET_ERGO(InitialHeapSize, (size_t)reasonable_initial);
|
||||
log_trace(gc, heap)(" Initial heap size %zu", InitialHeapSize);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
FLAG_SET_ERGO(MinHeapSize, MIN2(reasonable_minimum, InitialHeapSize));
|
||||
log_trace(gc, heap)(" Minimum heap size %zu", MinHeapSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GCArguments::initialize_heap_sizes() {
|
||||
initialize_alignments();
|
||||
initialize_heap_flags_and_sizes();
|
||||
|
||||
@ -40,10 +40,13 @@ protected:
|
||||
virtual void initialize_heap_flags_and_sizes();
|
||||
virtual void initialize_size_info();
|
||||
|
||||
size_t limit_heap_by_allocatable_memory(size_t size);
|
||||
|
||||
DEBUG_ONLY(void assert_flags();)
|
||||
DEBUG_ONLY(void assert_size_info();)
|
||||
|
||||
public:
|
||||
virtual void set_heap_size();
|
||||
virtual void initialize();
|
||||
|
||||
// Return the (conservative) maximum heap alignment
|
||||
|
||||
@ -283,7 +283,7 @@ JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose) {
|
||||
}
|
||||
|
||||
JVMFlag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
|
||||
// If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
|
||||
// If an overflow happened in GCArguments::set_heap_size(), MaxHeapSize will have too large a value.
|
||||
// Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
|
||||
if (value > (max_uintx - MaxHeapSize)) {
|
||||
JVMFlag::printError(verbose,
|
||||
|
||||
@ -35,7 +35,6 @@
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
#include "gc/shared/gcArguments.hpp"
|
||||
#include "gc/shared/gcConfig.hpp"
|
||||
#include "gc/shared/genArguments.hpp"
|
||||
#include "gc/shared/stringdedup/stringDedup.hpp"
|
||||
#include "gc/shared/tlab_globals.hpp"
|
||||
#include "jvm.h"
|
||||
@ -1489,138 +1488,6 @@ jint Arguments::set_ergonomics_flags() {
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
size_t Arguments::limit_heap_by_allocatable_memory(size_t limit) {
|
||||
size_t fraction = MaxVirtMemFraction * GCConfig::arguments()->heap_virtual_to_physical_ratio();
|
||||
size_t max_allocatable = os::commit_memory_limit();
|
||||
|
||||
return MIN2(limit, max_allocatable / fraction);
|
||||
}
|
||||
|
||||
// Use static initialization to get the default before parsing
|
||||
static const size_t DefaultHeapBaseMinAddress = HeapBaseMinAddress;
|
||||
|
||||
static size_t clamp_by_size_t_max(uint64_t value) {
|
||||
return (size_t)MIN2(value, (uint64_t)std::numeric_limits<size_t>::max());
|
||||
}
|
||||
|
||||
void Arguments::set_heap_size() {
|
||||
// Check if the user has configured any limit on the amount of RAM we may use.
|
||||
bool has_ram_limit = !FLAG_IS_DEFAULT(MaxRAMPercentage) ||
|
||||
!FLAG_IS_DEFAULT(MinRAMPercentage) ||
|
||||
!FLAG_IS_DEFAULT(InitialRAMPercentage);
|
||||
|
||||
const physical_memory_size_type avail_mem = os::physical_memory();
|
||||
|
||||
// If the maximum heap size has not been set with -Xmx, then set it as
|
||||
// fraction of the size of physical memory, respecting the maximum and
|
||||
// minimum sizes of the heap.
|
||||
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
|
||||
uint64_t min_memory = (uint64_t)(((double)avail_mem * MinRAMPercentage) / 100);
|
||||
uint64_t max_memory = (uint64_t)(((double)avail_mem * MaxRAMPercentage) / 100);
|
||||
|
||||
const size_t reasonable_min = clamp_by_size_t_max(min_memory);
|
||||
size_t reasonable_max = clamp_by_size_t_max(max_memory);
|
||||
|
||||
if (reasonable_min < MaxHeapSize) {
|
||||
// Small physical memory, so use a minimum fraction of it for the heap
|
||||
reasonable_max = reasonable_min;
|
||||
} else {
|
||||
// Not-small physical memory, so require a heap at least
|
||||
// as large as MaxHeapSize
|
||||
reasonable_max = MAX2(reasonable_max, MaxHeapSize);
|
||||
}
|
||||
|
||||
if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
|
||||
// Limit the heap size to ErgoHeapSizeLimit
|
||||
reasonable_max = MIN2(reasonable_max, ErgoHeapSizeLimit);
|
||||
}
|
||||
|
||||
reasonable_max = limit_heap_by_allocatable_memory(reasonable_max);
|
||||
|
||||
if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
|
||||
// An initial heap size was specified on the command line,
|
||||
// so be sure that the maximum size is consistent. Done
|
||||
// after call to limit_heap_by_allocatable_memory because that
|
||||
// method might reduce the allocation size.
|
||||
reasonable_max = MAX2(reasonable_max, InitialHeapSize);
|
||||
} else if (!FLAG_IS_DEFAULT(MinHeapSize)) {
|
||||
reasonable_max = MAX2(reasonable_max, MinHeapSize);
|
||||
}
|
||||
|
||||
#ifdef _LP64
|
||||
if (UseCompressedOops) {
|
||||
// HeapBaseMinAddress can be greater than default but not less than.
|
||||
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
|
||||
if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) {
|
||||
// matches compressed oops printing flags
|
||||
log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least %zu "
|
||||
"(%zuG) which is greater than value given %zu",
|
||||
DefaultHeapBaseMinAddress,
|
||||
DefaultHeapBaseMinAddress/G,
|
||||
HeapBaseMinAddress);
|
||||
FLAG_SET_ERGO(HeapBaseMinAddress, DefaultHeapBaseMinAddress);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t heap_end = HeapBaseMinAddress + MaxHeapSize;
|
||||
uintptr_t max_coop_heap = max_heap_for_compressed_oops();
|
||||
|
||||
// Limit the heap size to the maximum possible when using compressed oops
|
||||
if (heap_end < max_coop_heap) {
|
||||
// Heap should be above HeapBaseMinAddress to get zero based compressed
|
||||
// oops but it should be not less than default MaxHeapSize.
|
||||
max_coop_heap -= HeapBaseMinAddress;
|
||||
}
|
||||
|
||||
// If the user has configured any limit on the amount of RAM we may use,
|
||||
// then disable compressed oops if the calculated max exceeds max_coop_heap
|
||||
// and UseCompressedOops was not specified.
|
||||
if (reasonable_max > max_coop_heap) {
|
||||
if (FLAG_IS_ERGO(UseCompressedOops) && has_ram_limit) {
|
||||
log_debug(gc, heap, coops)("UseCompressedOops disabled due to "
|
||||
"max heap %zu > compressed oop heap %zu. "
|
||||
"Please check the setting of MaxRAMPercentage %5.2f.",
|
||||
reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage);
|
||||
FLAG_SET_ERGO(UseCompressedOops, false);
|
||||
} else {
|
||||
reasonable_max = max_coop_heap;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _LP64
|
||||
|
||||
log_trace(gc, heap)(" Maximum heap size %zu", reasonable_max);
|
||||
FLAG_SET_ERGO(MaxHeapSize, reasonable_max);
|
||||
}
|
||||
|
||||
// If the minimum or initial heap_size have not been set or requested to be set
|
||||
// ergonomically, set them accordingly.
|
||||
if (InitialHeapSize == 0 || MinHeapSize == 0) {
|
||||
size_t reasonable_minimum = clamp_by_size_t_max((uint64_t)OldSize + (uint64_t)NewSize);
|
||||
reasonable_minimum = MIN2(reasonable_minimum, MaxHeapSize);
|
||||
reasonable_minimum = limit_heap_by_allocatable_memory(reasonable_minimum);
|
||||
|
||||
if (InitialHeapSize == 0) {
|
||||
uint64_t initial_memory = (uint64_t)(((double)avail_mem * InitialRAMPercentage) / 100);
|
||||
size_t reasonable_initial = clamp_by_size_t_max(initial_memory);
|
||||
reasonable_initial = limit_heap_by_allocatable_memory(reasonable_initial);
|
||||
|
||||
reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, MinHeapSize);
|
||||
reasonable_initial = MIN2(reasonable_initial, MaxHeapSize);
|
||||
|
||||
FLAG_SET_ERGO(InitialHeapSize, (size_t)reasonable_initial);
|
||||
log_trace(gc, heap)(" Initial heap size %zu", InitialHeapSize);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
FLAG_SET_ERGO(MinHeapSize, MIN2(reasonable_minimum, InitialHeapSize));
|
||||
log_trace(gc, heap)(" Minimum heap size %zu", MinHeapSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This must be called after ergonomics.
|
||||
void Arguments::set_bytecode_flags() {
|
||||
if (!RewriteBytecodes) {
|
||||
@ -3677,7 +3544,7 @@ jint Arguments::apply_ergo() {
|
||||
if (result != JNI_OK) return result;
|
||||
|
||||
// Set heap size based on available physical memory
|
||||
set_heap_size();
|
||||
GCConfig::arguments()->set_heap_size();
|
||||
|
||||
GCConfig::arguments()->initialize();
|
||||
|
||||
|
||||
@ -273,12 +273,6 @@ class Arguments : AllStatic {
|
||||
static void set_use_compressed_oops();
|
||||
static jint set_ergonomics_flags();
|
||||
static void set_compact_headers_flags();
|
||||
// Limits the given heap size by the maximum amount of virtual
|
||||
// memory this process is currently allowed to use. It also takes
|
||||
// the virtual-to-physical ratio of the current GC into account.
|
||||
static size_t limit_heap_by_allocatable_memory(size_t size);
|
||||
// Setup heap size
|
||||
static void set_heap_size();
|
||||
|
||||
// Bytecode rewriting
|
||||
static void set_bytecode_flags();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user