Talk about the G1 garbage collector

As an efficient garbage collector, G1 was added to JVM in JDK7, and replaced CMS as the default garbage collector in JDK9.

1 Garbage Collector Review

1.1 The new generation

The new generation adopts the copy algorithm. There are three main garbage collectors, Serial, Parallel New, and Parallel Scavenge. The characteristics are as follows:

  • Serial: Single-threaded collector, running in serial mode, when GC is in progress, other threads will stop working. Under single-core CPU, the collection efficiency is the highest.
  • Parallel New: A multi-threaded version of Serial, the default collector for the new generation. Under multi-core CPU, it is more efficient and can be used in conjunction with the CMS collector.
  • Parallel Scavenge: A multi-threaded collector that pays more attention to throughput and is suitable for tasks with less interaction. It cannot be used in conjunction with CMS.

1.2 Old generation

  • Serial Old: Using mark-sorting (compression) algorithm, single-threaded collection.
  • Parallel Old: Using mark-sorting (compression) algorithm, it can be used in conjunction with Parallel Scavenge
  • CMS: Concurrent Mark Sweep, using the mark-sweep algorithm, the collection thread can work together with the user thread. Disadvantages of CMS: low throughput, inability to handle floating garbage, mark-and-sweep algorithm will generate a lot of memory fragments, and will switch to Serial old after concurrent mode failure.
  • G1: Divide the heap into multiple regions of equal size. The new generation and the old generation are no longer physically separated. It has good performance in scenarios with multi-core CPUs and large memory. The new generation uses the copy algorithm, and the old generation uses the mark-compression (collation) algorithm.

2 Introduction to G1

2.1 Getting to know G1 for the first time

The G1 garbage collector is mainly used in multi-processor and large-memory scenarios. It has five attributes: generational, incremental, parallel (concurrent in most cases), stop the word, and mark finishing.

  • Generational: Like other garbage collectors, G1 divides the heap into a young generation and an old generation. Garbage collection is mainly in the young generation, and the young generation has the highest recycling efficiency. Occasionally collections are also done in the old generation.
  • Incremental: In order to shorten the STW time during garbage collection, G1 uses incremental and step-by-step recycling. G1 builds a predictable pause time model by analyzing the previous behavior and pause time of the application, and uses this information to predict the garbage collection situation during the pause time. For example: G1 will first reclaim those memory areas with high collection efficiency (most of these areas are recyclable garbage, which is why it is called G1).
  • Parallelism and Concurrency: To improve throughput, some operations require STW. Some operations that take a lot of time, such as whole heap operations (like global marking) can be executed concurrently, and can be executed concurrently in parallel with the application .
  • Marking: G1 mainly uses the marking algorithm for garbage collection. The marking phase is the same as the "marking and clearing" algorithm, but after marking, the recyclable objects will not be cleaned up directly. Instead, all surviving objects will be moved to one end, and then Directly reclaim the memory beyond the boundary after the move. As shown below:

picture

We know that one of the goals of the garbage collector is that the STW (stop the word) be as short as possible. Using the predictable pause time model, G1 sets a STW target time for garbage collection (set by the -XX:MaxGCPauseMillis parameter, the default is 200ms), and G1 completes garbage collection within this time as much as possible without additional configuration achieve high throughput.

G1 is committed to finding the best balance between latency and throughput in the following applications and environments:

  • The heap size reaches more than 10GB, and more than half of the space is occupied by surviving objects
  • As the system runs for a long time, the rate of object allocation and promotion changes rapidly
  • There is a lot of memory fragmentation in the heap
  • The pause time during garbage collection should not exceed a few hundred milliseconds to avoid long pauses caused by garbage collection.

If G1 is used in JDK8, we can use the parameter -XX:+UseG1GC to enable it. G1 is not a real-time collector. It tries its best to complete the pause time set by MaxGCPauseMillis with high performance, but it cannot absolutely guarantee that the collection will be completed within this time.

2.2 Heap layout

G1 divides the entire heap into regions of equal size. Each region is a continuous virtual memory, and a region is the basic unit of memory allocation and recovery. As shown below:

picture

The region in red with "S" represents the survivor of the new generation, the region in red without "S" represents the new generation eden, the region in light blue without "H" represents the old generation, and the region in light blue with "H" represents the middle of the old generation of large objects. Different from the previous memory allocation strategy of G1, the survivor, eden, and old age areas may be discontinuous.

When G1 is at a standstill, it can recycle the entire new generation region, and the objects in the new generation region are either copied to the survivor area or copied to the old generation region. At the same time, each pause can reclaim part of the memory of the old generation, and copy the old generation from one region to another.

2.3 about regions

In the previous section, we saw that the entire heap memory is divided into multiple regions of equal size by G1. Each heap can have about 2048 regions, and the size of each region is 1~32 MB (must be a power of 2). The size of the region is set by -XX:G1HeapRegionSize, so according to the default value, the maximum memory that G1 can manage is about 32MB * 2048 = 64G.

2.4 Large objects

A large object refers to an object whose size exceeds half of a region. A large object can span multiple regions. When allocating memory for a large object, it will be directly allocated in the old generation and will not be allocated in the eden area.

As shown in the figure below, a large object occupies two and a half regions. When allocating memory to a large object, consecutive regions must be allocated from one region. Before the large object is recycled, the last region cannot be allocated to other objects.

picture

When are large objects recycled ? Usually, dead large objects will only be recycled during the Cleanup pause phase or FullGC after the mark ends. However, there is an exception for array large objects of basic types (such as bool arrays, all integer arrays, float arrays, etc.), and G1 will reclaim these dead large objects during any GC pause. This is enabled by default, but can be disabled with the -XX:G1EagerReclaimHumongousObjects parameter.

When allocating large objects, GC pauses may occur prematurely because they take up too much space. Every time G1 allocates a large object, it will check whether the current heap memory usage exceeds the initial heap usage threshold IHOP (The Initiating Heap Occupancy Percent). If the current heap usage exceeds the IHOP threshold, the initial mark will be triggered immediately. See Section 4 for details on the initial mark .

Large objects are never moved even during FullGC. This may lead to premature FullGC or unexpected OOM, because although there is still a lot of free memory at this time, these memory are memory fragments in the region.

3 memory allocation

Although G1 divides the heap memory into multiple regions, the concept of new generation and old generation still exists. G1 has added two parameters to control the memory size of the new generation, -XX:G1NewSizePercent (default is equal to 5), -XX:G1MaxNewSizePercent (default is equal to 60). That is to say, the size of the new generation accounts for 5% to 60% of the entire heap memory by default.

According to the previous introduction, a heap can allocate about 2048 regions, and each region can be up to 32M. In this way, the size of the entire heap managed by G1 can be up to 64G, and the size range occupied by the new generation is 3.2G to 38.4G.

For -XX:G1NewSizePercent and -XX:G1MaxNewSizePercent, the following issues need attention:

  1. If -Xmn is set, do these two parameters take effect?

To take effect, for example, if the heap size is 64G and -Xmn3.2G is set, it is equivalent to -XX:G1NewSizePercent=5 and -XX:G1MaxNewSizePercent=5, because 3.2G/64G = 5%.

  1. If -XX:NewRatio is set, do these two parameters take effect?

To take effect, for example, if the heap size is 64G, if you set -XX:NewRatio=3, it is equivalent to -XX:G1NewSizePercent=25 and -XX:G1MaxNewSizePercent=25. Because the young generation: the old generation = 1: 3, it means that the young generation accounts for 1/4 = 25%.

  1. If only one of -XX:G1NewSizePercent and -XX:G1MaxNewSizePercent is set, will these two parameters still take effect?

The parameter set does not take effect, and the default values ​​are used for both parameters.

  1. If the two parameters -XX:G1NewSizePercent and -XX:G1MaxNewSizePercent are both in effect, when will the dynamic capacity be expanded?

It is related to the parameter -XX:GCTimeRatio. This parameter is an integer between 0 and 100 (the default for G1 is 9, and the default for other collectors is 99). If the value is n, the system will spend no more than 1/(1+n) time for garbage collection. Therefore, G1 defaults to a maximum of 10% of the time for garbage collection, and if the garbage collection time exceeds 10%, it will trigger expansion. If the expansion fails, a Full GC is initiated.

4 Garbage collection

The garbage collection of G1 is performed alternately in two stages of Young-Only and Space-Reclamation. As shown below:

picture

The young-only stage gradually fills up the old generation area with objects, and the space-reclamation stage not only reclaims the memory of the young generation, but also reclaims the memory of the old generation incrementally. Restart the young-only phase when finished.

4.1 Young-only

The Young-only phase process is as follows:

picture

This stage starts with the ordinary young-only GC. The young-only GC moves some objects to the old age. When the space occupied by the old age reaches IHOP, G1 stops the ordinary young-only GC and starts the initial mark (Initial Mark) .

  • Initial marking: In addition to the ordinary young-only GC, this process will also start the concurrent marking process, which determines that the marked surviving objects in the old age will be retained in the next space-reclamation phase. This process will not be STW, and it is possible that the normal young-only GC will start before the mark is over. This marking process needs to be completed after two processes of remarking (Remark) and cleaning (Cleanup).

  • Relabeling: This process will STW, this process does global references and class unloading.

    Between the remark and cleanup phases, G1 concurrently computes object survival information, which is used to update internal data structures during the cleanup phase.

  • Cleanup phase: This node reclaims all free areas and decides whether to perform a space-reclamation next. If so, only a single young-only GC is performed, and the young-only phase is over.

Regarding IHOP, by default, G1 will observe how much time is spent marking in the marking cycle and how much memory is allocated in the old generation, so as to automatically determine an optimal IHOP, which is called adaptive IHOP. If this function is turned on, because there is not enough observation data to determine the IHOP at the beginning, G1 will use the parameter -XX:InitiatingHeapOccupancyPercent to specify the initial IHOP. You can use the -XX:-G1UseAdaptiveIHOP parameter to turn off adaptive IHOP, so that IHOP is a fixed value specified by the parameter -XX:InitiatingHeapOccupancyPercent. Adaptive IHOP sets the occupancy rate of the old generation in this way. When the occupancy rate of the old generation = the maximum occupancy rate of the old generation - the value of the parameter -XX:G1HeapReservePercent, the first Mixed GC in the space-reclamation phase is started. Here parameter -XX:G1HeapReservePercent is used as an additional cache value.

Regarding marking, marking uses the SATB algorithm. At the beginning of the initial marking, G1 saves a virtual image of the heap, and the surviving objects of this image are also considered alive during the subsequent marking process. This has the problem that if some objects die during the marking process, they are still alive for the space-reclamation phase (with a few exceptions). Compared with other garbage collectors, this will cause some dead objects to be incorrectly retained, but it provides better throughput for the marking phase, and these incorrectly retained objects will be recycled in the next marking phase.

In the young-only stage, the region of the new generation is recycled. Every time young-only ends, G1 always adjusts the size of the new generation. G1 can use the parameters -XX:MaxGCPauseTimeMillis and -XX:PauseTimeIntervalMillis to set the target pause time. These two parameters are obtained from long-term observation of the actual pause time. He will calculate how much time it takes to reclaim the same size of new generation memory based on how many objects are copied during GC and how the objects are related to each other.

If there are no other restrictions, G1 will adjust the size of the young area to a value between -XX:G1NewSizePercent and -XX:G1MaxNewSizePercent to meet the pause time requirement.

4.2 Space-reclamation

This stage consists of multiple Mixed GCs, which not only recycle young generation garbage, but also recycle old generation garbage. This phase ends when G1 finds that reclaiming more old generation regions cannot release more free space. After that, periodically start a new Young-only phase again. When G1 runs out of memory when collecting surviving object information, G1 will do a Full GC and STW.

In the space-reclamation phase, G1 will try to reclaim as much old generation memory as possible during the GC pause time. At this stage, the memory size of the new generation is adjusted to the minimum allowed value set by -XX:G1NewSizePercent. As long as there is a reclaimable old generation region, it will be added to the recycling collection until the addition will exceed the target pause time. During a certain GC pause time, G1 will obtain the final collection of regions to be recycled according to the efficiency of region recovery in the old age (high efficiency priority collection) and the remaining available time.

The number of old generation regions to be reclaimed during each GC pause is limited by the number of candidate region sets divided by the parameter value -XX:G1MixedGCCountTarget. The parameter -XX:G1MixedGCCountTarget specifies the maximum number of times Mixed GC is triggered in a cycle, and the default value is 8. For example, -XX:G1MixedGCCountTarget adopts the default value of 8, and the candidate region set has 200 regions, so 25 regions are collected during each pause. The candidate region set is all regions in the old generation whose occupancy rate is lower than -XX:G1MixedGCLiveThresholdPercent.

When the reclaimable space occupancy rate in the region set to be reclaimed is lower than the parameter value -XX:G1HeapWastePercent, Space-Reclamation ends.

4.3 Memory tension

Evacuation failure is triggered when the surviving objects of the application occupy a large amount of memory, so that there is not enough space to copy the remaining objects. At this time, in order to complete the current garbage collection, G1 will keep the surviving objects in the new position unchanged, and will not copy the objects that have not been moved and copied, and only adjust the references between objects.

Evacuation failure will cause some additional overhead, but generally will be as fast as other young GC. After the evacuation failure is completed, G1 will continue to resume the execution of the application as normal. G1 will assume that the evacuation failure occurs at the end of the GC, when most objects have been moved, and there is enough memory to continue executing the application until the end of the mark and the start of space-reclamation. If this assumption is not true (that is, there is not enough memory to execute the application), G1 can only initiate a Full GC in the end to compress the entire heap, and this process may be very slow.

5 Comparison with other collectors

5.1 Parallel GC

Parallel GC can compress and reclaim the memory of the old generation, but it can only operate on the old generation as a whole. G1 incrementally distributes the entire GC work incrementally over multiple shorter pause times, at the expense of throughput.

5.2 CMS

Similar to CMS, G1 reclaims memory in the old age concurrently. However, CMS adopts the mark-clear algorithm and will not deal with memory fragmentation in the old age, which will eventually lead to long-term FullGC.

5.3 G1 problem

Because of concurrent collection, the performance overhead of G1 will be greater, which may affect throughput.

5.4 Advantages of G1

G1 can reclaim memory that is completely empty or occupies a large space in the old generation during any GC period. This avoids some unnecessary GCs, as large amounts of memory can be freed very easily. This feature is enabled by default and can be disabled with the -XX:-G1EagerReclaimHumongousObjects parameter.

G1 can choose to deduplicate Strings in the entire heap in parallel. This function is disabled by default, and can be enabled with the parameter -XX:+G1EnableStringDeduplication.

Guess you like

Origin blog.csdn.net/qq_28165595/article/details/132122235