CMS garbage collector

introduce

    The full name of the CMS garbage collector is Concurrent Mark-Sweep Collector. Two points can be seen from the name. One is the use of concurrent collection, and the second is the collection algorithm used is Mark-Sweep. Therefore, it can also be inferred that the collector is characterized by low latency and has the problem of floating garbage. The characteristics of this collector are described in detail below.

CMS collector

    The CMS collector is designed for low latency and minimizes latency by executing several stages of garbage collection in parallel as much as possible. The CMS collector is a garbage collector of the old generation. Generally, there will be ParNew to cooperate with the execution (by default, it is also ParNew). ParNew also uses a parallel algorithm to perform young generation recycling. Of course, in addition to this, you can also choose to use the Serial collector to collect the young generation, but this is rarely used. The CMS collector we are talking about refers to the CMS collector in a broad sense, including the following: ParNew (Young) GC + CMS (Old) GC + Serial GC algorithm (to deal with the fact that the core CMS GC is not in time, expensive). This article focuses on the recycling of some CMS in the Old area.

Triggering conditions

    The trigger conditions of the CMS garbage collector are as follows:
1. If -XX:+UseCMSInitiatingOccupancyOnly is not set, the virtual machine decides whether to trigger it according to the collected data (it is recommended to bring this parameter).
2. The usage rate of the old age reaches the threshold CMSInitiatingOccupancyFraction, which is 92% by default, provided that the first parameter is configured.
3. The usage rate of the permanent generation reaches the threshold CMSInitiatingPermOccupancyFraction, which is 92% by default, provided that CMSClassUnloadingEnabled is enabled and the first parameter is configured.
4. The promotion guarantee of the new generation fails.

The collection phase of the CMS

    When the CMS collector collects the old generation, it is divided into the following stages: initial mark, concurrent mark, pre-clean, interruptible pre-clean, final mark, concurrent clear, concurrent reset. The operation process of each stage is as follows:     The CMS collector is introduced from these stages respectively.
        

initial mark

    The initial marking phase mainly does two things: one is to traverse the old generation objects that can be reached directly by GCRoot; the other is to traverse the old generation objects that are directly accessible from the new generation. Direct here refers to the first-level object directly related to GCRoot. The initial marking phase is fully STW and the referrer pauses. Through the -XX:+CMSParallelInitialMarkEnabled parameter, the parallel marking of this stage can be turned on, and multiple threads are used for marking to reduce the pause time.
    Which objects can be used as GCRoot:
1. All Java threads refer to the current stack frame, that is, the parameters, local variables and temporary values ​​of the reference type of the method being called.
2. Objects referenced by all static data structures
3. References in the String constant pool
4. Types referenced in the runtime constant pool

concurrent marking

    The concurrent marking phase is executed together with the application. This phase mainly does two things:
1. Trace the surviving objects marked in the initial marking, and mark these objects as reachable objects, such as A->B, A in the initial marking is identified, and B is identified in the concurrent marking phase.
2. Mark the cards of objects promoted from the new generation to the old generation in the concurrent phase, objects allocated directly in the old generation, and objects whose reference relationship has changed in the old generation as dirty, so as to avoid scanning the entire old generation in the re-marking phase.
Because the concurrent marking phase is executed together with the reference program, there will be a situation where A->B->C becomes A->C before. In this case, the C object cannot be marked in the concurrent marking phase. A three-color marking algorithm is used in the marking stage.
The three-color marking method divides the objects in the GC into three cases:
white: objects that have not been searched (white objects will be regarded as garbage objects)
gray: objects that are being searched
black: objects that have been searched (will not be treated as garbage objects) , will not be GC)
Suppose the object graph at the beginning is as follows: In the concurrent marking phase, the B object references the C object and becomes the A object references the C object, as follows, when scanning again, it will become the following figure. At this time, the C object It turns white, but it is obviously incorrect, so there are two ways to deal with this situation: 1. Record the object reference relationship before the object reference changes 2. Record the object reference relationship after the object reference changes








    These two ideas just correspond to the two processing methods of CMS and G1. Incremental update is used in CMS. As long as it is found in the write barrier that a reference to a white object is assigned to the field of a black object, the white object is turned into gray. . That is, when it is inserted, it is recorded. In G1, the STAB (snapshot-at-the-beginning) method is used, and all objects are recorded when deleted.

preclean

    This stage is selected to be closed by the parameter CMSPrecleaningEnabled, which is enabled by default. It mainly does two things
: 1. The concurrent marking stage allocates object A in Eden, and A refers to the old object B, then this stage marks B as the active object
2. Scans the concurrent marking Phase Dirty Card, remarking objects whose references were updated in the concurrent marking phase

Interruptible Preclean

    The purpose of this stage is to reduce the workload of re-marking and reduce the pause time. It mainly does two things:
1. Scan and process the objects in the DirtyCard
2. Process the objects in the old generation referenced by the new generation.
There are three conditions for exiting this stage. :
1. The 5-second exit controlled by the CMSMaxAbortablePrecleanTime parameter
2. The Eden area reaches the value configured by the CMSScheduleRemarkEdenPenetration parameter (default 50%)
3. The number of scans controlled by CMSMaxAbortablePrecleanLoops (default is 0, no exit) In
this stage, it is hoped that a Young GC can occur. In this way, the number of objects in the Eden area can be reduced, and the workload of re-marking can be reduced, because re-marking will scan the entire Eden area.

final mark

    The final mark is also called re-marking. This stage is also STW, and it mainly traverses three places:
1. Traverse Eden area, re-mark
2. Traverse DirtyCard, re-mark
3. Traverse GC Root, re-mark
because there are many areas traversed in this stage , so it may take a long time, and this stage is completely STW.
Through the CMSScavengeBeforeRemark parameter, you can force a YoungGC before the remarking phase. By setting the CMSParallelRemarkEnabled parameter, you can enable parallel remarking to speed up the remarking.

Concurrent cleanup

    Remove unused objects, reclaim the space they occupy and make them available for future use. This stage may generate floating garbage, and the number of compactions can be controlled through the parameters UseCMSCompactAtFullCollection and CMSFullGCsBeforeCompaction.

Concurrent reset

    This stage is the final stage, resetting the data structures of the CMS.

CMS log description

Here is a complete CMS log:

[java]  view plain copy  
 
  1. 2018-04-28T01:18:00.485+0800: 30991.893: [GC (CMS Initial Mark) [1 CMS-initial-mark: 845243K(1228800K)] 893692K(2611200K), 0.0195530 secs] [Times: use  
  2. r=0.04 sys=0.00, real=0.02 secs]  
  3. 2018-04-28T01:18:00.505+0800: 30991.913: [CMS-concurrent-mark-start]  
  4. 2018-04-28T01:18:00.944+0800: 30992.353: [CMS-concurrent-mark: 0.429/0.439 secs] [Times: user=0.94 sys=0.00, real=0.44 secs]  
  5. 2018-04-28T01:18:00.944+0800: 30992.353: [CMS-concurrent-preclean-start]  
  6. 2018-04-28T01:18:00.953+0800: 30992.362: [CMS-concurrent-preclean: 0.009/0.009 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]  
  7. 2018-04-28T01:18:00.953+0800: 30992.362: [CMS-concurrent-abortable-preclean-start]  
  8.  CMS: abort preclean due to time 2018-04-28T01:18:06.050+0800: 30997.459: [CMS-concurrent-abortable-preclean: 5.089/5.097 secs] [Times: user=5.92 sys=  
  9. 0.17, real=5.09 secs]  
  10. 2018-04-28T01:18:06.053+0800: 30997.462: [GC (CMS Final Remark) [YG occupancy: 222099 K (1382400 K)]30997.462: [Rescan (parallel) , 0.0285059 secs]309  
  11. 97.491: [weak refs processing, 0.0334976 secs]30997.524: [class unloading, 0.0806913 secs]30997.605: [scrub symbol table, 0.0359491 secs]30997.641: [s  
  12. crub string table, 0.0035671 secs][1 CMS-remark: 845243K(1228800K)] 1067342K(2611200K), 0.1878564 secs] [Times: user=0.38 sys=0.00, real=0.18 secs]  
  13. 2018-04-28T01:18:06.242+0800: 30997.650: [CMS-concurrent-sweep-start]  
  14. 2018-04-28T01:18:06.659+0800: 30998.068: [CMS-concurrent-sweep: 0.417/0.417 secs] [Times: user=0.55 sys=0.00, real=0.42 secs]  
  15. 2018-04-28T01:18:06.660+0800: 30998.069: [CMS-concurrent-reset-start]  
  16. 2018-04-28T01:18:06.663+0800: 30998.072: [CMS-concurrent-reset: 0.003/0.003 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  

  This log shows the various stages of CMS recycling. In the CMS Initial Mark stage, the old age capacity is 1228800K, and 845243K is currently used. This stage takes 0.0195530 seconds, and this time is STW; then proceed to the concurrent-mark stage , it took 0.429 seconds; the preClean stage took 0.009 seconds; the next step is the abortable-preclean stage, which took 5 seconds. The reason for the end is that the longest configuration of this stage runs for 5 seconds, and YoungGC does not occur in this stage. ; Next is the second STW, the Final Remark stage, 222099 K (1382400 K) are the occupation and total space of the young generation, respectively. This stage will also perform weak reference processing, class unloading and symbol table scanning, 845243K ( 1228800K) is the usage and total space of the old generation. This stage takes 0.1878564 seconds in total; after the marking is completed, the concurrent-sweep stage is started for concurrent clearing, and then concurrent-reset is run to reset the CMS data structure.

CMS failure handling

When running the CMS collector, two types of failures may occur

concurrent mode failure log

    When the old generation cannot accommodate the objects promoted by the new generation GC, the concurrent mode fails. The failure of the concurrent mode means that the CMS degenerates into a full STW Full GC, that is, Serial GC. The picture below shows the log when a concurrent mode failure occurs:     In this case, there are two aspects to consider: 1. Give background threads more opportunities to run. That is to say, start the concurrent collection cycle earlier. The CMS collector starts when the old age accounts for 60% of the usage ratio and starts at 70%. Obviously, the former has a greater chance of completing garbage collection. To achieve this configuration, the following two parameters can be set at the same time: -XX:CMSInitiatingOccupancyFraction=N and -XX:+UseCMSInitiatingOccupancyOnly. If these two parameters are set at the same time, the CMS can only decide whether to start CMS garbage collection according to the usage ratio of the old generation. 2. More threads to run CMS. The reason why the concurrent mode fails is because the speed of the CMS can not beat the speed of the object promotion to the old age. So you can speed up the CMS by giving it more threads. The number of background threads can be set by -XX:ConGCThreads=N. By default, the number of threads ConcGCThreads=(3+ParallelGCThreads)/4 is calculated according to ParallelGCThreads. The value of ParallelGCThreads can be set by the -XX:ParallelGCThreads parameter. It does not mean that the more threads are set to run the CMS, the better, because the CMS will completely occupy a CPU when it is running, so when the CPU is relatively tight, this value should be set carefully.



promotion failure

    There is enough space in the old generation, but due to severe fragmentation, it cannot accommodate the promoted objects in the new generation, and the promotion fails. The picture below shows the log when promotion fails:     The reason for promotion failure is severe fragmentation, so the solution to this problem is how to reduce the problem of fragmentation. CMS provides two parameters to defrag and compress. The function of -XX:+UseCMSCompactAtFullCollection is to defragment and compress the fragments during FullGC. -XX:CMSFullGCsBeforeCompaction=* This parameter is to set how many times to perform a defragmentation and compression of the memory of the old generation when performing FullGC. The fragmentation problem can be effectively optimized by setting these two parameters. It should also be noted that defragmentation and compression is a time-consuming operation, so it also needs to be set carefully.

Some parameter descriptions of CMS

 

Combined with the parameter configuration that has been mentioned above, some parameter descriptions of CMS are given below:
-XX:+UseConcMarkSweepGC activates the CMS collector
-XX:ConcGCThreads sets the number of CMS threads
-XX:+UseCMSInitiatingOccupancyOnly only decides whether to use the ratio of the old age Perform CMS
-XX:CMSInitiatingOccupancyFraction Set the percentage of memory usage that triggers CMS old age recycling
-XX:+CMSParallelRemarkEnabled Run the final marking phase in parallel to speed up the final marking
-XX:+UseCMSCompactAtFullCollection Sort every time CMS Full GC is triggered Fragmentation
-XX:CMSFullGCsBeforeCompaction=* After several CMS Full GCs, defragmentation is performed once
. -XX:+CMSClassUnloadingEnabled allows CMS to collect permanent bands, which will not be collected by default
-XX:+CMSScavengeBeforeRemark Force a Minor GC before final marking
-XX: +ExplicitGCInvokesConcurrent When calling System.gc(), execute parallel gc, this parameter is only valid under CMS or G1

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325123114&siteId=291194637