Fundamentals 8 min read

Java Performance Tuning Part 5: Hands‑On GC Optimization from G1 to ZGC

This article walks through Java GC tuning by defining low‑latency and high‑throughput goals, comparing major collectors, presenting G1 and ZGC configuration examples, and demonstrating a real‑world payment system case where pause times were reduced from 150‑200 ms to under 50 ms.

Coder Trainee
Coder Trainee
Coder Trainee
Java Performance Tuning Part 5: Hands‑On GC Optimization from G1 to ZGC

Hello, I'm Lao J. After covering JVM memory, CPU spikes, memory leaks, and thread‑pool tuning, this fifth installment dives into the "deep water" of GC tuning.

1. GC Tuning Mindset

Low latency : aim for GC pause time < 50 ms.

High throughput : keep GC CPU time under 5% of total runtime.

Low latency and high throughput are often contradictory:

To lower latency you need more frequent GCs, which raises CPU overhead and reduces throughput.

To raise throughput you reduce GC frequency, which lengthens each pause and increases latency.

Therefore, before tuning, decide whether your primary goal is low latency or high throughput.

2. Choosing the Right GC Algorithm

Serial – Heap < 1 GB, pause in seconds, high throughput, enable with -XX:+UseSerialGC Parallel – Heap 1‑4 GB, pause hundreds of ms, high throughput, enable with -XX:+UseParallelGC G1 – Heap 4‑64 GB, pause < 200 ms, medium‑high throughput, enable with -XX:+UseG1GC ZGC – Heap > 16 GB, pause < 1 ms (independent of heap size), medium throughput, enable with -XX:+UseZGC Shenandoah – Heap > 16 GB, pause < 1 ms, medium throughput, enable with -XX:+UseShenandoahGC Selection advice :

Small apps / batch jobs – choose Parallel GC (throughput‑first, pause acceptable).

Web apps / micro‑services (4‑16 GB) – choose G1 GC (balanced latency and throughput, default recommendation).

Large‑memory, low‑latency workloads (>16 GB) – choose ZGC (sub‑millisecond pauses).

Reactive / real‑time systems – choose ZGC or Shenandoah for ultra‑low latency.

3. G1 GC Tuning in Practice

3.1 Core Parameters

# Basic configuration (4‑core, 8 GB RAM, 4 GB heap)
-XX:+UseG1GC
-Xms4g -Xmx4g

# Target pause time (default 200 ms)
-XX:MaxGCPauseMillis=100

# Adjust young generation size (default 5%)
-XX:G1NewSizePercent=5
-XX:G1MaxNewSizePercent=60

# Concurrent threads (default 1/4 of CPU cores)
-XX:ConcGCThreads=2

# Trigger Mixed GC when old generation reaches this percent
-XX:InitiatingHeapOccupancyPercent=45

3.2 Tuning Flow

┌─────────────────────────────────────────────────────────────────┐
│                G1 GC Tuning Flow                           │
├─────────────────────────────────────────────────────────────────┤
│                     Problem: GC pause > 200 ms               │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Step 1: Lower MaxGCPauseMillis                           │ │
│ │   -XX:MaxGCPauseMillis=50                               │ │
│ │   Observe GC logs to confirm reduction                  │ │
│ └─────────────────────────────────────────────────────────┘ │
│   ▼                                                       │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Step 2: If Mixed GC is frequent, adjust                │ │
│ │   InitiatingHeapOccupancyPercent=60                     │ │
│ │   Delay Mixed GC trigger to reduce frequency            │ │
│ └─────────────────────────────────────────────────────────┘ │
│   ▼                                                       │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Step 3: If throughput is low, increase                 │ │
│ │   ConcGCThreads (default is CPU/4)                     │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

3.3 Real‑World Tuning Case

Scenario: A payment system with an 8 GB heap using default G1. GC pause 150‑200 ms, requirement < 50 ms.

Investigation:

GC logs show frequent Young GCs (~every 2 s).

Each Young GC takes 80‑120 ms.

Analysis:

Frequent Young GCs indicate the young generation is too small.

Objects have short lifetimes but Survivor space is insufficient.

Tuning:

-XX:+UseG1GC
-Xms8g -Xmx8g
-XX:MaxGCPauseMillis=50          # target 50 ms
-XX:G1NewSizePercent=10          # increase young gen from 5% to 10%
-XX:G1MaxNewSizePercent=70       # max young gen 70%
-XX:InitiatingHeapOccupancyPercent=50
-XX:ConcGCThreads=4              # 4‑core concurrent threads

Result: Young GC frequency dropped to every 5‑8 s, pause time reduced to 30‑50 ms, meeting the target.

4. ZGC in Practice

4.1 Enabling ZGC

# Enable ZGC (Java 11+)
-XX:+UseZGC -Xms16g -Xmx16g

# Note: ZGC works best with heap ≥ 8 GB; smaller heaps do not showcase its advantages.

4.2 ZGC Tuning Parameters

# Concurrent threads (default CPU/4)
-XX:ConcGCThreads=4

# GC trigger interval (seconds)
-XX:ZCollectionInterval=300

# Allocation spike tolerance
-XX:ZAllocationSpikeTolerance=2

# GC logging
-Xlog:gc*,gc+time=debug:file=zgc.log:time,uptime,level,tags

4.3 ZGC vs G1 Comparison (16 GB heap)

Max pause: G1 50‑200 ms, ZGC < 1 ms.

Throughput: G1 95‑98%, ZGC 90‑95%.

CPU overhead: G1 low, ZGC medium.

Applicable scenario: G1 – general use; ZGC – ultra‑low latency.

5. Three‑Step GC Tuning Methodology

1. Diagnose – Observe GC logs to locate issues; tools: GCViewer, GCEasy.

2. Analyze – Determine whether the bottleneck is throughput or latency.

3. Tune – Adjust JVM flags, then verify the effect.

6. Next Episode Preview

Java Performance Tuning Part 6 will cover a comprehensive case study, moving from Full GC analysis to achieving a 200 ms response time.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMzgcPerformance TuningGClow-latencyhigh-throughputg1
Coder Trainee
Written by

Coder Trainee

Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.