Using JAVA_MAX_MEM_RATIO on container JBoss EAP 7/8 image
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 7.x
- 8.x
- Red hat OpenShift Container Platform (OCP)
- 4.x
Issue
- We configure the JAVA_INITIAL_MEM_RATIO and JAVA_MAX_MEM_RATIO in the deployment's configmap file and only the JAVA_INITIAL_MEM_RATIO works as expected.
- Question for MaxRAMPercentage: is better set via JAVA_MAX_MEM_RATIO rather than setting via JAVA_OPTS directly?
Resolution
In OpenJDK containers, the user can set the heap ratio (percentage) of the container size MaxRAMPercentage via JAVA_MAX_MEM_RATIO as long as the image is started via the default initialization scripts. Setting via the environment variable JAVA_MAX_MEM_RATIO is preferred than setting MaxRAMPercentage directly via JAVA_OPTS and Xmx directly, which decouples the heap from the container size.
The user can set those environment variables directly in the deployment or via a configmap, which is a file associated with the deployment. If a configmap is used, make sure it is correctly associated with the deployment (i.e. update the deployment or deploymentconfig file with that), so the environment variable defined there are properly set and used.
In case EAP Operator is used, see Setting Env variables in JWS and JBoss EAP Operator in Openshift 4.
Example
Example setting the environment directly in a deployment file:
$ oc get deployment eap-example-straight -o yaml
apiVersion: apps/v1
kind: Deployment
...
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: eap-example-straight
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: eap-example-straight
spec:
containers:
- env:
- name: JAVA_MAX_MEM_RATIO
value: "51"
Root Cause
As explained on How to change JVM memory options using Openshift images with Java?, the JVM is container aware, so JAVA_MAX_MEM_RATIO sets the Xmx as a percentage of the container total size:
JAVA_MAX_MEM_RATIOat 50% means the Xmx will be 50% of the detected cgroups size.JAVA_MAX_MEM_RATIOat 80% means the Xmx will be 50% of the detected cgroups size.
For details on InitialRAMPercentage and MaxRAMPercentage see the solution Usage of Java flags InitialRAMPercentage and MaxRAMPercentage and should -XX:+UseContainerSupport flag be used in OpenJDK images?.
The heap size should be dynamic and coupled with the container size via cgroups.
Environment variables
| Environment Variable | Purpose | Higher percentage means | Lower percentage means |
|---|---|---|---|
| JAVA_MAX_MEM_RATIO | Sets the Xmx in a percentage of the container, where 50% setting is 50% of the container (default to 80% on OpenJDK - previously was 50%) | Higher percentage of Xmx means more of the container memory will be heap | A lower percentage of Xmx means all the container memory will be off-heap (do not set below 20%) |
| JAVA_MAX_INITIAL_MEM | Sets the Xms in a percentage of the Xmx, where 50% setting is 50% of the Xmx, and the default is 25% - 1/4 of the Xmx (defaults to 25%) | Higher percentage of Xms means the minimal heap usage closer to Xmx (up to 100% of Xmx) | Lower percentage of Xms means the minimal memory usage further from Xmx (min value is 0%) |
FAQ
Q1. Should the user tune JAVA_MAX_MEM_RATIO ?
A1. Usually discouraged but yes, as long they understand the increase of heap, is the decrease of off-heap inside a container. And vice-versa. EAP 7/SSO/DG should be kept around 50% usage for most use cases. Unless benchmarks show the opposite provide any benefit. Do not set JAVA_MAX_MEM_RATIO at 100% because this would mean 0% percent for off-heap, which is never the case.
Q2. Should the user play with the JAVA_MAX_INITIAL_MEM ?
A1.b Yes, setting JAVA_MAX_INITIAL_MEM at 100% means Xms will match the Xmx, which means the container memory won't go down upon GC cleaning.
Q3. Why keep JAVA_MAX_MEM_RATIO at 50%? What about JAVA_MAX_INITIAL_MEM at 25%?
A3. JAVA_MAX_MEM_RATIO at 50% of the heap, means the remaining 50% of the container will be off-heap and this should avoid OOM/crash scenarios and give bandwidth for heap and off-heap operations, for example, EAP 7 cache state transfers. JAVA_MAX_INITIAL_MEM at 25% means the JVM can increase and decrease heap memory throughout the application run. Xmx == Xms incurs in the memory always be used.
Q4.Does the percentage set on JAVA_MAX_MEM_RATIO/JAVA_MAX_INITIAL_MEM interfere on the GC selection itself
A4. JAVA_MAX_MEM_RATIO/JAVA_MAX_INITIAL_MEM do not interfere directly with the GC selection. However, if the user does not impose any GC the default GC can change to SerialGC in case CPU <=1 and memory == 1Gb. If imposed, i.e. set manually not left for automatically selection, the GC will overwrite the default
Q5.Are the images EAP 8 and EAP 7 different?
A5. Yes. In several aspects, initialization, JVM settings, cgroups detection.
Diagnostic Steps
- Use VM.info for specific detecting values and seeing cgroups details
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.