Java Concurrent Mark & Sweep (CMS) algorithm operates by dividing the garbage collection process into multiple phases, concurrently marking and sweeping the memory regions without a significant pause. While its design brings benefits in terms of reduced pause times, it also introduces unique challenges that demand careful tuning and optimization. In this post, we will explore techniques to tune CMS GC for enhanced performance specifically. However, if you want to learn more basics, you may watch this Garbage Collection tuning talk delivered in the JAX London conference.
How to enable CMS GC?
You can enable the Concurrent Mark-Sweep (CMS) Garbage Collector in your Java application by adding the following JVM argument when launching your application:
-XX:+UseConcMarkSweepGC
Note: The CMS GC algorithm has been deprecated starting from JDK 9 & it has been completely removed in JDK 14, as no credible contributors stepped up to take on the maintenance of CMS. If your application runs on JDK 9 or later, it’s advisable to explore alternative Garbage Collectors like the Garbage-First (G1), Shenandoah, ZGC for optimal memory management.
When to use CMS GC?
You can consider using CMS GC for your application, if you have any one of the requirements:
a. JDK 14 and Below: CMS has been deprecated since JDK 9 and completely removed from JDK 14. Focus has shifted towards the Garbage-First (G1), Shenandoah and ZGC Garbage Collectors. However, for applications running on earlier JDK versions or with specific use cases, you can consider using CMS.
b. Low-latency Requirements: When your application demands low and predictable pause times, such as in real-time systems, CMS can be a suitable choice. Its concurrent nature allows it to perform garbage collection without significantly halting the application.
c. Frequent Object Creation and Deletion Environments: In situations where objects are created and become unreachable frequently, CMS can efficiently reclaim memory without causing prolonged interruptions, making it suitable for applications with dynamic memory patterns.
d. JVMs with Limited Resources: In environments where system resources, especially memory, are constrained, CMS can be a pragmatic choice as it aims to balance memory management efficiency with minimal disruption.
CMS GC tuning parameters
In this section let’s review important CMS GC tuning parameters that you can configure to your application.
1. -Xms and -Xmx
-Xms sets the initial heap size when the Java Virtual Machine (JVM) starts, and -Xmx sets the maximum heap size that the JVM can use. Setting both values to be the same value, ensures a fixed and non-resizable heap size. This configuration reduces hiccups associated with heap management, providing stability and predictable memory usage for your application. You may refer to this article to learn the detailed benefits of setting initial and maximum heap size to the same value
2. -XX:CMSInitiatingOccupancyFraction
Determines the heap occupancy percentage at which the CMS collector starts. This parameter helps in fine-tuning CMS initiation based on memory usage. For example, setting -XX:CMSInitiatingOccupancyFraction=75 means that CMS starts when the occupancy is 75%. The default value for this initiating occupancy threshold is approximately 92%, but the value is subject to change from release to release.
3. -XX:+UseCMSInitiatingOccupancyOnly
Restricts CMS to handle only full garbage collections. This can be useful in scenarios where you want to control CMS initiation more precisely. When set, CMS won’t start until the occupancy fraction is reached and a full garbage collection is required.
4. -XX:MaxGCPauseMillis
Sets the maximum acceptable pause time for CMS in milliseconds. This parameter helps in controlling the pause times during garbage collection. For instance, setting -XX:MaxGCPauseMillis=500 aims to limit pauses to 500 milliseconds.
5. -XX:+UseCMSCompactAtFullCollection and -XX:+CMSParallelRemarkEnabled
Enables parallel threads for the CMS collector, improving overall efficiency during garbage collection. These options enhance the parallelism in different phases of the CMS collection process.
6. -XXarallelCMSThreads and -XX:MaxParallelCMSThreads
Specifies the initial and maximum number of parallel threads for the CMS collector, influencing parallelism during the collection process.
7. -XX:+UseLargePages
The -XX:+UseLargePages option is a powerful tweak for optimizing Java heap performance. When enabled, it allows the Java Virtual Machine (JVM) to use large pages, typically 2 MB or more in size, for heap memory allocation. Below are the potential benefits of using -XX:+UseLargePages:
a. Reduced TLB Misses: Large pages diminish Translation Lookaside Buffer (TLB) misses, streamlining memory access and enhancing overall speed.
b. Improved TLB Efficiency: The larger page size optimizes TLB efficiency, leading to more efficient memory translations.
c. Enhanced Speed: With fewer TLB misses, the application experiences improved memory access speed, particularly beneficial for memory-intensive operations.
Note: While enabling large pages can deliver notable performance benefits, it’s essential to be aware that its effectiveness can vary depending on the application and system. Additionally, specific operating system-level configurations may be required.
Advanced CMS GC Options
As we explore the intricacies of Concurrent Mark-Sweep (CMS) Garbage Collection, let’s delve into advanced options that offer nuanced control over its behavior. These options go beyond the basics, providing additional tools for fine-tuning and optimizing CMS performance.
1. -XX:+UseCMSCompactAtFullCollection and -XX:+CMSParallelRemarkEnabled
Enables parallel threads for the CMS collector, improving overall efficiency during garbage collection. These options enhance the parallelism in different phases of the CMS collection process.
2. -XX:+UseCMSCompactAtFullCollection
Enabling this option instructs CMS to perform a compaction phase during a full garbage collection. This can help reduce fragmentation in the old generation, potentially improving memory utilization. However, note that compaction introduces additional overhead, and its impact should be carefully assessed based on your application’s characteristics.
3. -XX:CMSFullGCsBeforeCompaction
This option determines the number of full garbage collections that should occur before initiating a compaction phase. Adjusting this parameter allows you to control when compaction occurs, balancing the benefits of reduced fragmentation with the associated costs. Experiment with different values to find the optimal setting for your application.
4. -XX:+CMSClassUnloadingEnabled
This option allows the CMS collector to unload classes during garbage collection, potentially freeing up more memory. However, be cautious with this option, as it may have implications for certain application scenarios.
5. -XX:+CMSIncrementalMode and -XX:+CMSIncrementalPacing
These options enable incremental mode for the CMS collector, allowing garbage collection to occur in smaller, incremental steps. This can help reduce pause times, but it’s essential to evaluate the impact on overall throughput and responsiveness.
6. -XX:CMSInitiatingPermOccupancyFraction
If your application has a permanent generation (PermGen) space (common in Java 7 and earlier), this parameter determines the occupancy fraction at which CMS starts collecting the permanent generation.
7. -XX:CMSClassUnloadingMaxInterval
Specifies the maximum interval (in milliseconds) between CMS class unloading cycles. If class unloading is crucial for your application, tuning this parameter can influence how frequently class unloading occurs.
8. -XX:+CMSParallelInitialMarkEnabled
Enables parallel threads for the initial mark phase in the CMS collector. This can enhance the efficiency of the initial mark process, reducing the impact on pause times.
9. -XX:CMSIncrementalSafetyFactor
Specifies the factor by which CMS increases its duty cycle length during incremental mode. Adjusting this factor can impact the balance between incremental garbage collection and application throughput.
10. -XX:CMSMaxAbortablePrecleanTime
Sets the maximum time in milliseconds that CMS will spend in the abortable preclean phase. Adjusting this parameter may be necessary to optimize CMS performance, especially in scenarios where abortable precleaning takes longer than desired.
11. -XX:CMSWaitDuration
Defines the amount of time CMS waits for a requested collection to complete before initiating a new collection. Adjusting this parameter can influence the CMS collector’s aggressiveness in responding to memory demands.
12. -XX:CMSParallelRemarkEnabled
Enables parallel threads for the CMS collector during the remark phase. This can enhance the efficiency of the remark process, which is a crucial step in the CMS collection cycle.
13. -XX:CMSIncrementalDutyCycle
Sets the percentage of time that CMS should be active during an incremental collection cycle. Adjusting this parameter influences the balance between incremental collection and application throughput.
14. -XX:CMSIncrementalOffset
Specifies the percentage of the CMS duty cycle time that is devoted to the incremental update. This parameter can be fine-tuned to optimize the CMS incremental collection process.
15. -XX:CMSRescanMultiple
Controls the number of cards (regions of the heap) that are rescanned during a CMS cycle. Adjusting this parameter can impact the efficiency of the CMS collector.
16. -XX:CMSWaitDuration
Defines the amount of time CMS waits for a requested collection to complete before initiating a new collection. Adjusting this parameter can influence the CMS collector’s aggressiveness in responding to memory demands.
Studying CMS GC behavior
Studying the performance characteristics of CMS GC is best achieved by analyzing the GC log. The GC log contains detailed information about garbage collection events, memory usage, and other relevant metrics. There are several tools available that can assist in analyzing the GC log, such as GCeasy, IBM GC & Memory visualizer, HP Jmeter, Google Garbage cat. By using these tools, you can visualize memory allocation patterns, identify potential bottlenecks, and assess the efficiency of garbage collection. This allows for informed decision-making when fine-tuning CMS GC for optimal performance.
Conclusion
In this post, we have explored essential CMS JVM arguments, ranging from basic configurations like enabling CMS to advanced options such as compaction and trigger ratios. Moreover, considerations for large pages and class unloading shed light on optimizing memory usage. We hope it will be of help to you.