Summary
Increase the default MaxRAMPercentage
value on Linux for containerized systems which employ a container memory limit from 25% to 75%. This allows for better memory utilization when deployed on container orchestration systems such as Kubernetes with container memory limits already in place.
Problem
Deployments of the JVM in containers are common today. Many of those systems run on Kubernetes (K8S) and tune the memory needs on a per-pod or per-container basis. In such a scenario, the automatic container memory limit detection mechanism of the JVM kicks in. It derives the heap size from the detected physical memory. In case of a K8S pod which has a memory limit set, this would be the set memory limit. Most containerized deployments run a single application in that container/pod and expect the container to utilize the memory slice within its bounds as much as possible. The JVM default setting of 25% for MaxRAMPercentage
prevents this from happening. Only 1/4 of the container memory limit could be used for the Java heap before OutOfMemoryErrors would be thrown.
The default JVM setting of MaxRAMPercentage
of 25% makes sense for multi-user deployments. After all, other users might run other JVM processes on the same system that would compete for memory.
This is different In modern cloud environments. Applications are tuned at the container level in terms of resource allocation and expect applications to run well in such resource-constrained environments. Allowing the JVM to only use 25% of the container memory limit for its heap runs contrary to this goal as there is likely no other JVM to compete for heap/off-heap memory within that container. Most of the memory should be available for the heap and only a smaller portion for off-heap memory.
Solution
Increase the MaxRAMPercentage
value for containerized systems that also employ a container memory limit from 25% to 75% to increase the chance of better memory utilization. Do this only when OSContainer::has_memory_limit()
reports true
, indicating a containerized Linux system with a set container memory limit.
Specification
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 9bd45b0fec8..aa6e28b0ac1 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -4432,6 +4432,13 @@ void os::pd_init_container_support() {
OSContainer::init();
}
+// Called before ergonomic flags processing
+void os::initialize_max_ram_percentage() {
+ if (OSContainer::has_memory_limit()) {
+ FLAG_SET_ERGO_IF_DEFAULT(MaxRAMPercentage, 75.0);
+ }
+}
+
void os::Linux::numa_init() {
// Java can be invoked as
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index ee1f0a3b081..58f1e740f97 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -484,6 +484,7 @@ void os::init_before_ergo() {
// VM version initialization identifies some characteristics of the
// platform that are used during ergonomic decisions.
VM_Version::init_before_ergo();
+ LINUX_ONLY(initialize_max_ram_percentage();)
}
void os::initialize_jdk_signal_support(TRAPS) {
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index dde80806912..e6f5ec77cfd 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -256,6 +256,7 @@ class os: AllStatic {
static void initialize_initial_active_processor_count();
LINUX_ONLY(static void pd_init_container_support();)
+ LINUX_ONLY(static void initialize_max_ram_percentage();)
static void init(void); // Called before command line parsing
Compatibility Risks
General Linux deployments outside containers:
There is expected to be no difference in behaviour after this CSR.
Kubernetes:
Kubernetes has configuration options for "Memory requests" and "Memory limit". If "Memory limit" is not set, Kubernetes runs the container with no (upper) memory limit. After this CSR, the JVM will use 25% of the container host memory for its heap size as before. If "Memory limit" is set on the Kubernetes deployment level, then each JVM will use 75% of the set container limit for its heap size within that container. The expectation is for there to be only one JVM. However, this could be problematic for containers which spawn many JVMs, like maven builds. In that case it is recommended to explicitly set -XX:MaxRAMPercentage to the old value.
Other Linux-based container orchestration environments
In general, for Linux containers with a memory limit set, any JVM process will be able to use more memory for the Java heap than it used to previously within that container. If that is not desired, then setting -XX:MaxRAMPercentage=25.0
will revert to the old behavour.
- csr of
-
JDK-8350596 [Linux] Increase default MaxRAMPercentage for containerized workloads
-
- Closed
-