8305770: os::Linux::available_memory() should refer MemAvailable in /proc/meminfo

Reviewed-by: stuefe, sgehwolf, rcastanedalo, dholmes
This commit is contained in:
Yasumasa Suenaga
2023-05-12 08:48:29 +00:00
parent e1e758a7b4
commit b6bcbc0cbc
10 changed files with 83 additions and 23 deletions

View File

@@ -245,6 +245,10 @@ static bool is_close_to_brk(address a) {
return false;
}
julong os::free_memory() {
return Aix::available_memory();
}
julong os::available_memory() {
return Aix::available_memory();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -59,6 +59,7 @@ class os::Aix {
static int _extshm;
static julong available_memory();
static julong free_memory();
static julong physical_memory() { return _physical_memory; }
static void initialize_system_info();

View File

@@ -138,6 +138,10 @@ julong os::available_memory() {
return Bsd::available_memory();
}
julong os::free_memory() {
return Bsd::available_memory();
}
// available here means free
julong os::Bsd::available_memory() {
uint64_t available = physical_memory() >> 2;

View File

@@ -46,6 +46,7 @@ class os::Bsd {
static pthread_t _main_thread;
static julong available_memory();
static julong free_memory();
static julong physical_memory() { return _physical_memory; }
static void initialize_system_info();

View File

@@ -216,15 +216,8 @@ static bool suppress_primordial_thread_resolution = false;
// utility functions
julong os::available_memory() {
return Linux::available_memory();
}
julong os::Linux::available_memory() {
// values in struct sysinfo are "unsigned long"
struct sysinfo si;
julong avail_mem;
julong os::Linux::available_memory_in_container() {
julong avail_mem = static_cast<julong>(-1L);
if (OSContainer::is_containerized()) {
jlong mem_limit = OSContainer::memory_limit_in_bytes();
jlong mem_usage;
@@ -233,15 +226,57 @@ julong os::Linux::available_memory() {
}
if (mem_limit > 0 && mem_usage > 0) {
avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0;
log_trace(os)("available container memory: " JULONG_FORMAT, avail_mem);
return avail_mem;
}
}
return avail_mem;
}
julong os::available_memory() {
return Linux::available_memory();
}
julong os::Linux::available_memory() {
julong avail_mem = available_memory_in_container();
if (avail_mem != static_cast<julong>(-1L)) {
log_trace(os)("available container memory: " JULONG_FORMAT, avail_mem);
return avail_mem;
}
FILE *fp = os::fopen("/proc/meminfo", "r");
if (fp != nullptr) {
char buf[80];
do {
if (fscanf(fp, "MemAvailable: " JULONG_FORMAT " kB", &avail_mem) == 1) {
avail_mem *= K;
break;
}
} while (fgets(buf, sizeof(buf), fp) != nullptr);
fclose(fp);
}
if (avail_mem == static_cast<julong>(-1L)) {
avail_mem = free_memory();
}
log_trace(os)("available memory: " JULONG_FORMAT, avail_mem);
return avail_mem;
}
julong os::free_memory() {
return Linux::free_memory();
}
julong os::Linux::free_memory() {
// values in struct sysinfo are "unsigned long"
struct sysinfo si;
julong free_mem = available_memory_in_container();
if (free_mem != static_cast<julong>(-1L)) {
log_trace(os)("free container memory: " JULONG_FORMAT, free_mem);
return free_mem;
}
sysinfo(&si);
avail_mem = (julong)si.freeram * si.mem_unit;
log_trace(os)("available memory: " JULONG_FORMAT, avail_mem);
return avail_mem;
free_mem = (julong)si.freeram * si.mem_unit;
log_trace(os)("free memory: " JULONG_FORMAT, free_mem);
return free_mem;
}
julong os::physical_memory() {

View File

@@ -51,12 +51,16 @@ class os::Linux {
static size_t _default_large_page_size;
static julong available_memory_in_container();
protected:
static julong _physical_memory;
static pthread_t _main_thread;
static julong available_memory();
static julong free_memory();
static int active_processor_count();
static void initialize_system_info();

View File

@@ -830,6 +830,10 @@ julong os::available_memory() {
return win32::available_memory();
}
julong os::free_memory() {
return win32::available_memory();
}
julong os::win32::available_memory() {
// Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect
// value if total memory is larger than 4GB

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2023, 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
@@ -63,6 +63,7 @@ class os::win32 {
return _processor_level;
}
static julong available_memory();
static julong free_memory();
static julong physical_memory() { return _physical_memory; }
// load dll from Windows system directory or Windows directory

View File

@@ -1011,7 +1011,7 @@ void CompileBroker::init_compiler_threads() {
void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
julong available_memory = os::available_memory();
julong free_memory = os::free_memory();
// If SegmentedCodeCache is off, both values refer to the single heap (with type CodeBlobType::All).
size_t available_cc_np = CodeCache::unallocated_capacity(CodeBlobType::MethodNonProfiled),
available_cc_p = CodeCache::unallocated_capacity(CodeBlobType::MethodProfiled);
@@ -1023,7 +1023,7 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
int old_c2_count = _compilers[1]->num_compiler_threads();
int new_c2_count = MIN4(_c2_count,
_c2_compile_queue->size() / 2,
(int)(available_memory / (200*M)),
(int)(free_memory / (200*M)),
(int)(available_cc_np / (128*K)));
for (int i = old_c2_count; i < new_c2_count; i++) {
@@ -1070,8 +1070,8 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
ThreadsListHandle tlh; // name() depends on the TLH.
assert(tlh.includes(ct), "ct=" INTPTR_FORMAT " exited unexpectedly.", p2i(ct));
stringStream msg;
msg.print("Added compiler thread %s (available memory: %dMB, available non-profiled code cache: %dMB)",
ct->name(), (int)(available_memory/M), (int)(available_cc_np/M));
msg.print("Added compiler thread %s (free memory: %dMB, available non-profiled code cache: %dMB)",
ct->name(), (int)(free_memory/M), (int)(available_cc_np/M));
print_compiler_threads(msg);
}
}
@@ -1081,7 +1081,7 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
int old_c1_count = _compilers[0]->num_compiler_threads();
int new_c1_count = MIN4(_c1_count,
_c1_compile_queue->size() / 4,
(int)(available_memory / (100*M)),
(int)(free_memory / (100*M)),
(int)(available_cc_p / (128*K)));
for (int i = old_c1_count; i < new_c1_count; i++) {
@@ -1093,8 +1093,8 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
ThreadsListHandle tlh; // name() depends on the TLH.
assert(tlh.includes(ct), "ct=" INTPTR_FORMAT " exited unexpectedly.", p2i(ct));
stringStream msg;
msg.print("Added compiler thread %s (available memory: %dMB, available profiled code cache: %dMB)",
ct->name(), (int)(available_memory/M), (int)(available_cc_p/M));
msg.print("Added compiler thread %s (free memory: %dMB, available profiled code cache: %dMB)",
ct->name(), (int)(free_memory/M), (int)(available_cc_p/M));
print_compiler_threads(msg);
}
}

View File

@@ -310,7 +310,13 @@ class os: AllStatic {
return (_processor_count != 1);
}
// On some platforms there is a distinction between "available" memory and "free" memory.
// For example, on Linux, "available" memory (`MemAvailable` in `/proc/meminfo`) is greater
// than "free" memory (`MemFree` in `/proc/meminfo`) because Linux can free memory
// aggressively (e.g. clear caches) so that it becomes available.
static julong available_memory();
static julong free_memory();
static julong physical_memory();
static bool has_allocatable_memory_limit(size_t* limit);
static bool is_server_class_machine();