Backend Development 8 min read

JVM GC Tuning Case Study: Reducing YGC Frequency and Boosting Service Performance

The author describes a high‑QPS Java web service, analyzes its GC behavior using jstat and gceasy, applies JVM parameter adjustments such as enlarging the young generation, tweaking MaxTenuringThreshold and disabling biased locking, and achieves roughly a 15% overall performance gain with improved GC throughput.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
JVM GC Tuning Case Study: Reducing YGC Frequency and Boosting Service Performance

Hello everyone, I am Chen, and I recently performed a performance optimization on a high‑QPS web service by tuning JVM parameters, resulting in about a 15% overall performance improvement.

Project Overview: The service maintains over 1.5K QPS per machine, runs on an old machine with an 8 GB heap (4 GB young generation) using the ParNew + CMS garbage collector.

Current GC Situation: Using jstat and GC logs, the average GC pause is around 60 ms, but Young GC (YGC) occurs very frequently—about once per second, sometimes twice per second—causing noticeable response latency.

GC logs are enabled with the following JVM options:

-XX:+PrintGCDateStamps : prints timestamps for GC events.

-XX:+PrintTenuringDistribution : prints generation information.

-XX:+PrintGCApplicationStoppedTime : prints GC pause time.

-XX:+PrintGCApplicationConcurrentTime : prints time between GC pauses.

-XX:+PrintGCDetails : prints detailed GC information.

-Xloggc:../gclogs/gc.log.date : specifies GC log file path.

Analyzing the logs with gceasy shows a GC throughput of 95% (5 % of runtime spent in GC) and confirms that most pauses are YGC.

Analysis and Adjustments:

Frequent YGC

To reduce YGC frequency, the young generation size was doubled from 4 GB to 8 GB, increasing the total heap to 12 GB. This halved the YGC frequency and raised GC throughput to 97.75%.

Generation Tuning

The MaxTenuringThreshold was lowered to 4, promoting objects that survive more than four generations directly to the old generation, reducing copy overhead between survivor spaces.

Biased Lock Pause

Observed ~18 ms pauses were linked to biased lock revocation. Adding -XX:-UseBiasedLocking disables biased locking and eliminates these pauses.

Results: After the JVM parameter changes, load testing showed a noticeable performance boost without severe GC issues. YGC frequency dropped by half, GC throughput improved to 97.75%, average GC pause increased slightly to 66 ms, and CMS pause times grew as expected. Business‑impact metrics also showed a significant reduction in timeout requests caused by GC.

Key Takeaways: The author plans to create a series covering JVM fundamentals, specific performance optimization points, tuning tools, and real‑world case studies.

Conclusion: The GC tuning was successful, deepening the author's understanding of JVM GC mechanisms, though further study on the old generation and CMS is needed. Continuous monitoring and timely adjustments remain essential for performance optimization.

Promotion: The author invites readers to follow the "Code Monkey Technical Column" public account to obtain PDF collections of Spring Cloud, Spring Boot, and MyBatis advanced tutorials.

backendJavaJVMperformance optimizationGC tuning
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login 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.