dotCMS / dotCMS/core

Auto-tune JVM GC algorithm in setenv.sh based on available vCPUs

Open
#36,258 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS : Containerization Team : Platform Type : Task
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Description

The Tomcat setenv.sh startup script uses a static GC configuration regardless of the container's available CPU resources. On Java 25 we can make smarter, automatic GC choices that improve throughput and latency without any operator tuning.

Current behavior

JAVA_OPTS_MEMORY is a hardcoded string with G1PeriodicGCInterval=10000 applied unconditionally, regardless of whether the container has 1 vCPU or 32.

Proposed behavior

Detect available vCPUs at container startup and select the appropriate GC:

vCPUs GC selected Rationale
1–3 G1GC (default) + G1PeriodicGCInterval=10000 Returns memory to OS on idle; low overhead on small containers
4+ ZGC (-XX:+UseZGC) Java 25 defaults to GenerationalZGC; sub-millisecond pauses; scales with cores

SerialGC is explicitly excluded — it is not appropriate for a long-running, multi-threaded web server (Tomcat threads, Quartz, OSGi, async jobs) even on a single-core container.

CPU count detection:

_cpus=$(nproc 2>/dev/null || grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo 2)

Base memory flags remain constant across all tiers:

  • -XX:MaxRAMPercentage=72.0
  • -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50
  • -Djdk.nio.maxCachedBufferSize=262144

Full override: set JAVA_OPTS_MEMORY before the script runs — auto-tune is skipped entirely.

Acceptance Criteria

To be refined. (Quick draft — details to be added.)

  • On a 1-vCPU container, G1GC + G1PeriodicGCInterval=10000 is selected at startup
  • On a 4+-vCPU container, -XX:+UseZGC is selected at startup
  • Startup log prints the selected GC and detected vCPU count
  • Setting JAVA_OPTS_MEMORY externally bypasses auto-selection entirely
  • SerialGC is never selected

Additional Context

  • Java 25 GenerationalZGC is the default ZGC mode — -XX:+UseZGC alone is sufficient
  • The direct memory block (JAVA_OPTS_DIRECT) already uses a similar cgroup-aware auto-tune pattern; this change follows the same idiom
  • MaxRAMPercentage and jdk.nio.maxCachedBufferSize do not need to scale with CPU count

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in setenv.sh and compare the existing cgroup-aware pattern in the JAVA_OPTS_DIRECT block. Trace how JAVA_OPTS_MEMORY is initialized and overridden, then verify startup output and JVM flags for 1–3 and 4+ vCPUs, including that an external override bypasses auto-selection and SerialGC is never chosen.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, shell
Domain
devops, infrastructure
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.