1. Introduction
The Concurrent Mark Sweep (CMS) collector is a low-latency parallel garbage collector for a hotspot virtual machine. The focus of A CMS garbage collector is to minimize the pause time of the user thread during garbage collection. The shorter the pause time (low latency), the more suitable the application is to interact with the user, and the better the response speed can improve the user experience.
CMS garbage collector takes the shortest collection stop time as the goal, adopts the “mark-clean” algorithm, and carries out garbage collection in 4 steps, in which the initial marking and re-marking will STW, most of which are applied to the Internet site or the server of B/S system, JDK9 will be marked deprecated, JDK14 will be deleted. See JEP 363 for details.
Be insane. Unfortunately, a CMS, as an old garbage collector, cannot be applied to Parallel Scavenge and the newer collectors that exist in Jdk 1.4. So when you use a CMS in Jdk 1.5 to collect an old collection, A new generation can only choose one of the ParNew or Serial collectors.Before G1, CMS was widely used.
The CMS collector is enabled with the command-line option -xx :+UseConcMarkSweepGC.
2. How CMS works
One of the biggest innovations of the CMS was the idea of concurrent collection in the old days. Here’s a look at the process of concurrent collection. According to the official CMS documentation provided by Oracle
The overall concurrent collection usually consists of the following steps:
- Initial tag
- Concurrent tags
- To mark
- Concurrent remove
- Concurrent reset
Only The initialization and re-marking of The above steps STW(Stop The World). The remaining three steps are concurrent with The application mutator. Let’s look at The details of each step.
(1) Initial Mark
The initial tag goal is to tag all objects in the old age, includingObject directly associated with GC RootandAn object referenced from an active object in the young generation, the process will occur the first STW.
(2) Concurrent marking
In the concurrent marking phase, the application thread and the GC thread execute concurrently, so new objects or changes in object relationships may occur.
Such as:
- The object of the new generation rises to the old
- Allocate objects directly in the old age
- References to older objects have changed
For these objects, they need to be relabelled to prevent omission. In order to improve the efficiency of re-marking, the cards where the changed objects are located will be marked as Dirty in this stage. In this way, only the objects with Dirty cards need to be scanned in the future, so as to avoid scanning the whole old age.
Concurrent precleaningThis phase, which runs in parallel with the pre-marking thread and the application thread, will rescan the Dirty objects marked in the previous phase and mark the objects directly or indirectly referenced by the Dirty object, marking as Dirty for some heap areas where the object reference has changed.
In the pre-cleanup phase, these dirty objects are counted and objects reachable from them are marked
Precleaning can be terminated
Abortable concurrent precleanup This phase is intended to minimize the task for the next step. The default time is 5s. Expect to do a YGC in time, thus reducing the number of objects that mark the new generation reference the old generation when the next STW is scanned. Since this phase is a loop that does two things until abort occurs conditions such as: the number of iterations, how much work, how long, etc.
- Handle objects in the From and To fields, marking reachable older objects;
- As in the previous phase, the scan processes the objects in the Dirty Card.
(3) Final mark
A second STW occurs in this phase. The goal is to complete the marking of all the active objects in the old age. Since the previous pre-cleaning phase was concurrent, they may not be able to keep up with the rate of change in the application, so a second STW validation is required.
- Traversing Cenozoic objects and re-marking; (Generation will be partitioned and multithreaded)
- Re-label according to GC Roots;
- Go through the old Dirty cards and re-mark them. Most of the Dirty cards here have already been processed in the Preclean phase.
After the three marking phases, all the surviving objects of the old age are marked, and now the garbage collector will reclaim all unused objects by clearing the old age:
(4) Concurrent cleanup is executed at the same time with the application program, without STW. The purpose of this phase is to remove unused objects and reclaim the space they occupy for future use.
(5) Concurrent reset will clean up and restore various states in the CMS GC process, re-initialize CMS related data structures, and prepare for the next GC cycle. CSM execution log:
The 2020-10-21 T23:42:56. 214-0800: [CMS - concurrent - mark - start] 2020-10-21 T23:42:56. 245-0800: [CMS - concurrent - mark: 0.031/0.03secs] [Times: user= 0.03sys =0.00, real= 0.03secs] 2020-10-21t23:42:56.245-0800: [cms-concurrent-preclean-start] 2020-10-21T23:42:56.246-0800: [CMs-concurrent-preclean: 0.001/0.00secs] [Times: User =0.00 sys=0.00, real=0.00 secs] 2020-10-21t23:42:56.246-0800: [cms-concurrent-abortable-preclean-start] CMS: Abort preclean due to time 2020-10-21T23:43:01.313-0800: [cms-concurrent-abortable-preclean: 0.110/5.066 secs] [Times: User = 0.15sys =0.01, real= 5.07secs] 020-10-21t23:43:01.313-0800: [GC (CMS Final Remark) [YG occupancy: [Rescan (PARALLEL), 0.0032949 secs] 2020-10-21t23:43:01.316-0800: [Weak refs processing, 0.0000792 secs] 2020-10-21t23:43:01.317-0800: [class unloading, 0.0305113 secs] 2020-10-21 T23:43:01. 347-0800: [Scrub Symbol table, 0.0108352 secs] 2020-10-21t23:43:01.358-0800: [Scrub String table, 0.0009403 secs][1 CMS-remark: Secs [Times: User =0.03 sys=0.02, real=0.04 secs] 2020-10-21t23:43:03.360-0800: [cms-concurrent-sweep-start] 2020-10-21T23:43:01.367-0800: [CMs-concurrent-sweep-start: 0.007/0.007 secs] [Times: User =0.00 sys=0.00, real=0.00 secs] 2020-10-21t23:43:01.367-0800: [cms-concurrent-reset-start] 2020-10-21T23:43:01.367-0800: [cms-concurrent-reset: 0.000/0.000 secs] [Times: User sys = = 0.00 0.00, real = 0.00 secs]Copy the code
3. Advantages and disadvantages of CMS
3.1 the advantages
- Concurrent collection
- Low pause
Therefore, THE CMS collector is suitable for the scenario with more user interaction, focusing on the response speed of the service, can bring users a better experience! So when we do WEB development, we often use the CMS collector as the old collector!
3.2 disadvantages
-
Memory fragmentation can occur, resulting in insufficient space available to user threads after concurrent cleanup. In the case that the young generation cannot allocate large objects, Full GC has to be triggered early.
-
The CMS collector is very sensitive to CPU resources. In the concurrent phase, while it does not cause user threads to stall, it can slow the reference program by occupying a portion of the threads, resulting in lower overall throughput.
-
The CMS collector cannot handle floating garbage. A Concurrent Mode Failure may occur, resulting in another FUll GC. During the concurrent markup and cleanup phases, the user thread is working concurrently with the GC thread. As a result, the user thread is struggling to create objects during cleanup. CMS collector’s garbage collection action will not commonly so when completely unable to allocate memory, can pass “- XX: CMSInitiatingOccupancyFraction” parameter to set the CMS reserved memory space!
If the reserved space cannot meet the requirements of the CMS, a Concurrent Mode Failure occurs.
At that time the JVM will enable backup plan, that is, introduced in front of the Serial Old collector, this will lead to another Full GC, this price is very big, so CMSInitiatingOccupancyFraction this need according to the program setting up reasonable parameter Settings!
4. The classification of GC
The heap memory is divided into Eden, Survivor, and Tenured/Old Spaces, and the use of Minor, Major, and Full GC events is often confusing throughout the process. Each of them is described below.
4.1 Minor GC
Reclaiming memory from the young generation space (including the Eden and Survivor regions) is called a Minor GC
This definition is both clear and easy to understand. However, there are some interesting things to note when Minor GC events occur:
- Minor GC is triggered when the JVM is unable to allocate space for a new object, such as when the Eden region is full. Therefore, the higher the allocation rate, the more frequently Minor GC is performed.
- When the pool is full, its contents are copied and the pointer tracks free memory from 0. The Eden and Survivor sections are marked and copied, replacing the classic marked, scanned, compressed, and cleaned operations. So there is no memory fragmentation in Eden and Survivor. The write pointer always stays at the top of the memory pool being used.
- When Minor GC is performed, the permanent generation is not affected. References from the permanent generation to the young generation are treated as GC roots, and references from the young generation to the permanent generation are directly ignored during the marking phase.
- Defying conventional wisdom, all Minor GCS trigger a “stop-the-world” that stops the application thread. For most applications, the delay caused by pauses is negligible. The truth is that most objects in Eden can be considered garbage and will never be copied to Survivor or old age Spaces. If the reverse is true, most of the new objects in Eden will not be eligible for GC, and the pause time of Minor GC will be much longer.
So the case for the Minor GC is fairly clear — each time the Minor GC cleans up the memory of the younger generation.
When is the YGC triggered?
In most cases, objects are allocated directly in the Eden region of the young generation, and if there is not enough space in the Eden region, then YGC (Minor GC) is triggered, which only handles the new generation region. Because most objects are retrievable for a short period of time, very few objects survive YGC and are moved to the S0 region (using the copy algorithm).
When the next YGC is triggered, the living objects in Eden and S0 are moved to S1, and Eden and S0 are cleared at the same time. When the YGC is fired again, the regions to be processed are Eden and S1 (i.e. S0 and S1 are swapped roles). With each YGC, the age of the surviving object is increased by one.
4.2 Major GC vs. Full GC
You should note that these terms are currently not formally defined either in the JVM specification or in garbage collection research papers. But we can see at first glance that these definitions are correct based on what we already know, and that Minor GC should be designed to clean up young band memory simply:
- The Major GC is the cleanup permanent generation.
- Full GC is to clean up the entire heap space – both young and permanent generations.
When is Full GC triggered?
There are four ways in which an object can enter the old age:
- In YGC, the To Survivor section is not large enough To hold surviving objects, and objects go straight To the old age.
- After multiple YGCs, if the age of the surviving object reaches a set threshold, it is promoted to the old age.
- Dynamic age determination rule: if the sum of the size of an object of the same age in the “To Survivor” area accounts for more than half of the space in the “To Survivor” area, objects older than this age will enter the old age directly without reaching the default generation age.
- Large objects: – XX: PretenureSizeThreshold launch parameters control, if the object size is greater than this value, can bypass the Cenozoic, direct distribution in old age.
FGC (Major GC) is triggered when the number of objects promoted to the old age is greater than the remaining space in the old age. FGC handles both the new and old age areas. In addition, FGC can also be triggered in the following four situations:
- The old memory usage reaches a certain threshold (which can be adjusted by parameters), and the FGC is triggered directly.
- Space allocation guarantee: Before YGC, it checks to see if the maximum available continuous space in the old generation is greater than the total space of all objects in the new generation. If not, YGC is unsafe and the HandlePromotionFailure parameter is set to allow guaranteed failures. If not, Full GC is triggered. If so, the maximum available continuous space in the old age is further checked to see if it is greater than the average size of the objects promoted to the old age, and if it is smaller, Full GC is triggered.
- Metaspace expands when it runs out of space, and FGC is triggered when it expands to the value specified by the -xx :MetaspaceSize parameter.
- When either system.gc () or Runtime.gc() are explicitly called, FGC is triggered.
5. Set CMS GC parameters
Concurrent Mark Sweep (CMS) is the most commonly used JVM garbage collector today. This is not an explanation of how CMS works, just a few basic notes to help you understand what’s going on:
- CMS is a garbage collector based on concurrency that uses a marker removal algorithm. CMS tries to eliminate long GC pauses (STW) by having GC threads execute concurrently with user threads as much as possible.
- CMS does not do garbage collection for the new generation, but only for the old generation by default. In addition, CMS can also enable garbage collection (or meta-space) for permanent generations to avoid Full GC due to PermGen space depletion. For JDK6, this parameter is controlled by -xx :+CMSClassUnloadingEnabled, which is disabled by default before JDK8. JDK8 is enabled by default.
- CMS is to be paired with a new generation of garbage collectors called “generational collection”. The new generation of collectors that work with CMS are the Serial collector and the ParNew collector. We typically use the ParNew collector that supports multithreaded execution.
- When the CMS GC policy is used, the GCS can be classified into Young GCS (also known as Minor GCS), Old GCS (also known as Major GC and CMS GC), and Full GCS. Full GC is the garbage collection of the entire heap. The STW takes a long time and has great impact on services. Therefore, you should avoid Full GC
5.1 JVM Parameter Configuration
After understanding the meaning and impact of each parameter, the following JVM parameter configurations are summarized, which can be used almost without adjustment:
-Xmx32g -Xms32g -Xmn1g Xss256k
-XX:SurvivorRatio=2
-XX:MaxPermSize=256m
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:ParallelGCThreads=10
-XX:ParallelCMSThreads=16
-XX:+CMSParallelRemarkEnabled
-XX:MaxTenuringThreshold=15
-XX:+UseCMSCompactAtFullCollection
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:+CMSClassUnloadingEnabled
-XX:-DisableExplicitGC
-XX:+HeapDumpOnOutOfMemoryError
-verbose:gc-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCDateStamps
-Xloggc:/app/log/hbase/gc-hbase-REGIONSERVER-`hostname`-`date +%Y%m%d`.log
Copy the code
If the heap is 64G or above, -XMN can be adjusted to 2G, other parameters unchanged or fine tuning. Some important JVM parameters are described below.
Key parameter analysis
The following parameter analysis is based on the use of CMS GC strategy, where CMS GC represents the old garbage collection and Young GC represents the new garbage collection. (1) the -xmx – Xms, – Xmn
-
-xmx and -xms indicate the maximum heap size and initialization size of the JVM respectively.
- -xmx is equivalent to -xx :MaxHeapSize
- -xms is equivalent to -xx :InitialHeapSize.
-
-xmn indicates the size of the new generation, which is equivalent to -xx :MaxNewSize or -xx :NewSize. The setting of this parameter has a significant impact on GC performance. A small setting will affect CMS GC performance, while a large setting will affect Young GC performance. For example, the 32G heap size can be set to 1g, 64G heap size can be set to 2G, usually high performance.
(2) – Xss
- -xx :ThreadStackSize; default: 1M; recommended: 256K
(3) – XX: SurvivorRatio
- In the new generation, the ratio of Eden zone to Survivor zone is 8 by default. If this parameter is set too high, the CMS GC takes too long. Therefore, you are advised to set it to a smaller value so that the short-life objects can be fully collected in the Young zone and the number of objects promoted to the Old zone can be reduced to improve THE CMS GC performance.
(4) – XX: + UseParNewGC, – XX: + UseConcMarkSweepGC
- Means that the parallel collector ParNew is used to collect the new generation, and the concurrent marker clearing collector CMS is used to collect the old generation.
(5) – XX: ParallelGCThreads – XX: ParallelCMSThreads
- Indicates the number of parallel threads that the Young GC and CMS GC work respectively. You are advised to set the number of parallel threads according to the number of processors.
6 – XX: MaxTenuringThreshold
- The age threshold for an object to be promoted from the new generation to the old age (the age of the object left for each Young GC plus one). The default value is 15, indicating that it takes 15 GCS for an object to be promoted from the new generation to the old age. The CMS GC performance is adversely affected if the value is too small. You are advised to set the value to the default value.
7 – XX: + UseCMSCompactAtFullCollection
- Since the CMS GC generates memory fragmentation and is compressed only during the Full GC (Full GC cannot be avoided using the CMS garbage collector). This parameter indicates that the compression function of Full GC is enabled to reduce memory fragmentation.
Today – XX: + UseCMSInitiatingOccupancyOnly – XX: CMSInitiatingOccupancyFraction
-
– XX: trigger CMS GC CMSInitiatingOccupancyFraction said to use the old s threshold, generally set to 70 ~ 80 (in percentage), set up is too small will increase the frequency of CMS GC found, set too much can lead to concurrent mode failure or promotion. The default is -1, indicating that the CMS GC is automatically triggered by the JVM.
-
– XX: + UseCMSInitiatingOccupancyOnly said CMS GC based on CMSInitiatingOccupancyFraction trigger only, If you do not set this parameter, the JVM will only according to CMSInitiatingOccupancyFraction trigger CMS GC for the first time, subsequent will trigger automatically. You are advised to set both parameters.
Pet-name ruby – XX: + CMSClassUnloadingEnabled
- Indicates that the CMS enables garbage collection (or meta space) for the permanent generation to avoid Full GC caused by the permanent generation space exhaustion.
6. Write at the end
Hotspot has so many GC collectors, what is the difference between Serial GC, Prallel GC, CMS GC?
- Use Serial GC if you want to minimize memory and parallel overhead
- Prgradient GC is used if you want to maximize throughput
- Use the CMS GC if you want to minimize GC interrupts and pause times (low latency)
Also note that the G1 garbage collector is used by default in Jdk9 to mark CMS as obsolete. Remove the CMS garbage collector in Jdk14.
Related articles
- Java8 official website Concurrent tag Scan (CMS) collector
- Analysis and solution of 9 common CMS GC problems in Java
- Implementation of CMS garbage collection algorithm