提交 d9cc1e05 编写于 作者: T tschatzl

7112912: Message "Error occurred during initialization of VM" on boxes with lots of RAM

Summary: Ergonomics now also takes available virtual memory into account when deciding for a heap size. The helper method to determine the maximum allocatable memory block now uses the appropriate OS specific calls to retrieve available virtual memory for the java process. In 32 bit environments this method now also searches for the maximum actually reservable amount of memory. Merge previously separate implementations for Linux/BSD/Solaris into a single method.
Reviewed-by: jmasa, tamao
上级 1b842ee9
......@@ -167,20 +167,6 @@ julong os::physical_memory() {
return Bsd::physical_memory();
}
julong os::allocatable_physical_memory(julong size) {
#ifdef _LP64
return size;
#else
julong result = MIN2(size, (julong)3800*M);
if (!is_allocatable(result)) {
// See comments under solaris for alignment considerations
julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
result = MIN2(size, reasonable_size);
}
return result;
#endif // _LP64
}
////////////////////////////////////////////////////////////////////////////////
// environment support
......
......@@ -194,20 +194,6 @@ julong os::physical_memory() {
return Linux::physical_memory();
}
julong os::allocatable_physical_memory(julong size) {
#ifdef _LP64
return size;
#else
julong result = MIN2(size, (julong)3800*M);
if (!is_allocatable(result)) {
// See comments under solaris for alignment considerations
julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
result = MIN2(size, reasonable_size);
}
return result;
#endif // _LP64
}
////////////////////////////////////////////////////////////////////////////////
// environment support
......
......@@ -188,4 +188,66 @@ void os::Posix::print_uname_info(outputStream* st) {
st->cr();
}
bool os::has_allocatable_memory_limit(julong* limit) {
struct rlimit rlim;
int getrlimit_res = getrlimit(RLIMIT_AS, &rlim);
// if there was an error when calling getrlimit, assume that there is no limitation
// on virtual memory.
bool result;
if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) {
result = false;
} else {
*limit = (julong)rlim.rlim_cur;
result = true;
}
#ifdef _LP64
return result;
#else
// arbitrary virtual space limit for 32 bit Unices found by testing. If
// getrlimit above returned a limit, bound it with this limit. Otherwise
// directly use it.
const julong max_virtual_limit = (julong)3800*M;
if (result) {
*limit = MIN2(*limit, max_virtual_limit);
} else {
*limit = max_virtual_limit;
}
// bound by actually allocatable memory. The algorithm uses two bounds, an
// upper and a lower limit. The upper limit is the current highest amount of
// memory that could not be allocated, the lower limit is the current highest
// amount of memory that could be allocated.
// The algorithm iteratively refines the result by halving the difference
// between these limits, updating either the upper limit (if that value could
// not be allocated) or the lower limit (if the that value could be allocated)
// until the difference between these limits is "small".
// the minimum amount of memory we care about allocating.
const julong min_allocation_size = M;
julong upper_limit = *limit;
// first check a few trivial cases
if (is_allocatable(upper_limit) || (upper_limit <= min_allocation_size)) {
*limit = upper_limit;
} else if (!is_allocatable(min_allocation_size)) {
// we found that not even min_allocation_size is allocatable. Return it
// anyway. There is no point to search for a better value any more.
*limit = min_allocation_size;
} else {
// perform the binary search.
julong lower_limit = min_allocation_size;
while ((upper_limit - lower_limit) > min_allocation_size) {
julong temp_limit = ((upper_limit - lower_limit) / 2) + lower_limit;
temp_limit = align_size_down_(temp_limit, min_allocation_size);
if (is_allocatable(temp_limit)) {
lower_limit = temp_limit;
} else {
upper_limit = temp_limit;
}
}
*limit = lower_limit;
}
return true;
#endif
}
......@@ -476,24 +476,6 @@ julong os::physical_memory() {
return Solaris::physical_memory();
}
julong os::allocatable_physical_memory(julong size) {
#ifdef _LP64
return size;
#else
julong result = MIN2(size, (julong)3835*M);
if (!is_allocatable(result)) {
// Memory allocations will be aligned but the alignment
// is not known at this point. Alignments will
// be at most to LargePageSizeInBytes. Protect
// allocations from alignments up to illegal
// values. If at this point 2G is illegal.
julong reasonable_size = (julong)2*G - 2 * LargePageSizeInBytes;
result = MIN2(size, reasonable_size);
}
return result;
#endif
}
static hrtime_t first_hrtime = 0;
static const hrtime_t hrtime_hz = 1000*1000*1000;
const int LOCK_BUSY = 1;
......
......@@ -686,12 +686,17 @@ julong os::physical_memory() {
return win32::physical_memory();
}
julong os::allocatable_physical_memory(julong size) {
bool os::has_allocatable_memory_limit(julong* limit) {
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(ms);
GlobalMemoryStatusEx(&ms);
#ifdef _LP64
return size;
*limit = (julong)ms.ullAvailVirtual;
return true;
#else
// Limit to 1400m because of the 2gb address space wall
return MIN2(size, (julong)1400*M);
*limit = MIN2((julong)1400*M, (julong)ms.ullAvailVirtual);
return true;
#endif
}
......
......@@ -1552,6 +1552,15 @@ void Arguments::set_g1_gc_flags() {
}
}
julong Arguments::limit_by_allocatable_memory(julong limit) {
julong max_allocatable;
julong result = limit;
if (os::has_allocatable_memory_limit(&max_allocatable)) {
result = MIN2(result, max_allocatable / MaxVirtMemFraction);
}
return result;
}
void Arguments::set_heap_size() {
if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
// Deprecated flag
......@@ -1590,12 +1599,12 @@ void Arguments::set_heap_size() {
}
reasonable_max = MIN2(reasonable_max, max_coop_heap);
}
reasonable_max = os::allocatable_physical_memory(reasonable_max);
reasonable_max = limit_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 allocatable_physical_memory because that
// after call to limit_by_allocatable_memory because that
// method might reduce the allocation size.
reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
}
......@@ -1615,14 +1624,14 @@ void Arguments::set_heap_size() {
reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);
reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum);
reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum);
julong reasonable_initial = phys_mem / InitialRAMFraction;
reasonable_initial = MAX2(reasonable_initial, reasonable_minimum);
reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
reasonable_initial = os::allocatable_physical_memory(reasonable_initial);
reasonable_initial = limit_by_allocatable_memory(reasonable_initial);
if (PrintGCDetails && Verbose) {
// Cannot use gclog_or_tty yet.
......@@ -2608,9 +2617,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
initHeapSize = MIN2(total_memory / (julong)2,
total_memory - (julong)160*M);
// Make sure that if we have a lot of memory we cap the 32 bit
// process space. The 64bit VM version of this function is a nop.
initHeapSize = os::allocatable_physical_memory(initHeapSize);
initHeapSize = limit_by_allocatable_memory(initHeapSize);
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
......
......@@ -312,6 +312,9 @@ class Arguments : AllStatic {
static void set_use_compressed_oops();
static void set_ergonomics_flags();
static void set_shared_spaces_flags();
// limits the given memory size by the maximum amount of memory this process is
// currently allowed to allocate or reserve.
static julong limit_by_allocatable_memory(julong size);
// Setup heap size
static void set_heap_size();
// Based on automatic selection criteria, should the
......
......@@ -1962,6 +1962,10 @@ class CommandLineFlags {
product(uintx, InitialRAMFraction, 64, \
"Fraction (1/n) of real memory used for initial heap size") \
\
develop(uintx, MaxVirtMemFraction, 2, \
"Maximum fraction (1/n) of virtual memory used for ergonomically" \
"determining maximum heap size") \
\
product(bool, UseAutoGCSelectPolicy, false, \
"Use automatic collection selection policy") \
\
......
......@@ -184,7 +184,7 @@ class os: AllStatic {
}
static julong available_memory();
static julong physical_memory();
static julong allocatable_physical_memory(julong size);
static bool has_allocatable_memory_limit(julong* limit);
static bool is_server_class_machine();
// number of CPUs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册