wayne
wayne
Published on 2025-04-05 / 13 Visits
0
0

JAVA基础 - CMS,G1工作模式及调优小结 / JAVA Basics - CMS, G1 working mode and tuning summary

分代回收 Generational Collection

JAVA基础 - CMS,G1工作模式及调优小结_1.jpg

年轻代 Young Generation

包含一个Eden区和两个Survivor区,其中Eden区是对象产生的区域,Survivor区主要存储存活着但还不能晋升到老年代的对象
Consists of one Eden space and two Survivor spaces. The Eden space is where objects are initially created, while Survivor spaces hold objects that survived garbage collection but are not yet eligible for promotion to the old generation.

老年代 Old Generation

存放常驻内存对象的区域分代回收:当Eden区满时,会发生一次年轻代回收(Young GC),将仍存活的对象复制到一个Survivor区,当这个Survivor区满时,存活但没有达到晋升条件的对象全部被复制到另一个Survivor区中,达到晋升条件的对象则被放入老年代;当老年代空间使用率达到阈值,触发一次老年代回收(Old GC),将老年代中已经”死掉“的对象清理掉。需要注意的是,常说的Full GC是包含年轻代回收和老年代回收的。
Stores long-lived objects. Generational collection workflow: When the Eden space is full, a Young GC occurs, copying surviving objects to a Survivor space. When that Survivor space fills up, surviving objects not meeting promotion criteria are copied to the other Survivor space, while eligible objects are promoted to the old generation. When old generation space utilization reaches a threshold, an Old GC is triggered to clean up dead objects. Note: Full GC typically includes both Young and Old GC phases.

CMS

工作模式 Working Mechanism

CMS(Concurrent Mark Sweep),是一种以牺牲吞吐量为代价来缩短应用停顿时间的、垃圾收集过程中的大部分线程可以和应用线程并发执行的、面向老年代的、采用并发标记-清除算法的垃圾收集器,一次CMS GC的主要过程如下(灰色代表应用线程,黑色代表GC线程,其中Initial-mark和Remark阶段会暂停应用进程的执行,称为Stop the world(STW)):
CMS (Concurrent Mark Sweep) is an old-generation-oriented garbage collector using a concurrent mark-sweep algorithm. It prioritizes reduced application pause times over throughput, allowing most GC threads to run concurrently with application threads. A CMS GC cycle includes these phases (Gray: application threads; Black: GC threads. Initial-mark and Remark phases require Stop-The-World (STW) pauses):

JAVA基础 - CMS,G1工作模式及调优小结_2.jpg

  • Initial-mark(初始标记):标记老年代中所有能被年轻代和GC Root直接引用的对象(GC Root可以理解为本次GC时肯定不会被回收的部分对象,例如静态变量)
  • Initial-mark: Marks all old-generation objects directly reachable from the young generation and GC roots (GC roots are objects guaranteed to survive, like static variables).
  • Concurrent Marking(并发标记):Marking表示在应用程序运行的同时遍历Initial-mark阶段标记出来的对象,并递归扫描这些对象可达的所有对象(标记出老年代中所有存活的对象);
  • Concurrent Marking: Traverses objects marked in Initial-mark phase while the application runs, recursively scanning all reachable objects (marks all surviving objects in old generation).
  • Pre-cleaning(预清理):表示清理应用程序并发执行时出现的引用关系变化,例如刚晋升的对象和直接分配在老年代的对象
  • Pre-cleaning: Handles reference changes occurring during concurrent execution, such as newly promoted objects and objects directly allocated in old generation.
  • Remark(重新标记):暂停所有应用线程,重新扫描堆中的对象,在开始清理之前保持标记的正确性,查找在并发标记阶段漏掉的对象
  • Remark: Stops all application threads to rescan the heap, ensuring marking accuracy before cleanup and identifying objects missed during concurrent marking.
  • Concurrent Sweeping(并发清理):回收被标记为不可达的对象,这一阶段存活的对象并没有发生移动
  • Concurrent Sweeping: Reclaims objects marked as unreachable. Surviving objects are not moved during this phase.

内存碎片问题 Memory Fragmentation Issue

了解”标记-清除“算法的同学应该知道这种方法将会产生大量的内存碎片,这是因为:CMS将内存空间划分成一个个的网格,内存是连续分配的,但回收时只收集”死亡“的对象,不关心仍存活的对象。因此当应用程序执行一段时间后,必然会出现大量不连续的空闲内存碎片,导致老年代虽然还有很大剩余空间,但无法找到足够大的连续空间来分配申请的对象,触发Full GC(Promotion failed),会存在周期性Full GC的问题
The "mark-sweep" algorithm creates memory fragmentation. CMS divides memory into grids, allocating contiguously but only collecting dead objects. Over time, this leads to discontinuous free memory fragments. Although the old generation may have sufficient free space, it cannot find contiguous space for large object allocations, triggering Full GC (Promotion failed) and periodic Full GC issues.

浮动垃圾问题 Floating Garbage Issue

在并发清理阶段,用户线程仍在运行,如果产生新的垃圾,在此次GC中无法得到处理,只能等到下次清理,这些对象称为Floating Garbage。当Floating Garbage过多导致内存空间不足,那么CMS GC过程中就会出现Full GC(Concurrent Mode Failure)
During concurrent sweeping, application threads continue running and may generate new garbage ("Floating Garbage") that cannot be processed in the current GC cycle. Excessive Floating Garbage causing memory insufficiency triggers Full GC (Concurrent Mode Failure) in CMS.

G1

G1是Garbage-First的缩写,与CMS相比,G1是一种有内存整理过程的、优先收集存活对象最少区域的、面向年轻代和老年代的、物理空间不必连续的垃圾收集器。
G1 (Garbage-First) is a generational collector for both young and old generations. Compared to CMS, it performs memory compaction, prioritizes regions with least live objects, and uses non-contiguous physical memory regions.

JAVA基础 - CMS,G1工作模式及调优小结_3.jpg

  • Region:整个堆空间被尽可能地划分为约2048个Region(单个Region大小为1~32MB),每个Region都可以是Eden/Survivor/Old区的任意一个
  • Region: The heap is divided into ~2048 regions (1-32MB each). Each region can be Eden, Survivor, or Old.
  • Remembered Sets(RSets):每个Region对应一个RSet,用来跟踪指向该区域的对象引用,避免全堆扫描
  • Remembered Sets (RSets): Each region has an RSet tracking incoming object references to avoid full-heap scanning.
  • Collection Sets(CSets):CSets是一次GC中将被回收的Region集合,GC时所有CSet区域中的存活对象都会被移动到新的区域
  • Collection Sets (CSets): A group of regions to be collected during GC. All live objects in CSets are evacuated to new regions.
  • Humongous Object:超过Region大小一半的对象称为巨型对象,会在创建时直接被分配到Old Regions中
  • Humongous Object: Objects exceeding half a region's size are directly allocated to Old regions.

工作模式 Working Mechanism

G1是同时面向年轻代和老年代的垃圾收集器,因此包括Young GC 和 Mixed GC 两种工作模式。
G1 operates in two modes: Young GC and Mixed GC, handling both young and old generations.

Young GC

  • Young 区由一系列不连续的Region组成,因此可以很容易在GC过程中扩/缩容
  • The young generation consists of discontinuous regions, enabling flexible expansion/shrinkage during GC.
  • Young GC 会将存活对象转移到Survivor和老年代
  • Young GC evacuates surviving objects to Survivor and Old generations.
  • Young GC 会计算 Eden 区和 Survivor 区在下次回收之前所需的的空间,然后动态调整新生代Region个数,从而达到控制Young GC耗时的目的
  • Young GC calculates required space for Eden/Survivor before next collection and dynamically adjusts young region count to control GC pause times.

Mixed GC

  • 当老年代使用的空间超过阈值(IHOP),会触发 Global Concurrent Marking 统计出回收收益高的老年代Region,然后开始一系列连续的Mixed GC,这个过程称为Concurrent Marking Cycle Phases
  • When old generation usage exceeds IHOP threshold, Global Concurrent Marking identifies high-value old regions for collection, initiating a series of Mixed GCs (Concurrent Marking Cycle Phases).
  • 一系列连续的Mixed GC中,GC的最大次数和单次回收的空间大小可以通过参数**-XX:G1MixedGCCountTarget** 和-XX:G1OldCSetRegionThresholdPercent 进行配置
  • Parameters -XX:G1MixedGCCountTarget and -XX:G1OldCSetRegionThresholdPercent control maximum Mixed GC cycles and per-cycle old region collection limits.
  • 除了GC次数超过最大值以外,如果可回收空间的比例小于参数 -XX:G1HeapWastePercent ,也会中断Mixed GC周期
  • Mixed GC cycles may also abort if reclaimable space ratio falls below -XX:G1HeapWastePercent.
  • 面向全堆:Mixed GC 是面向全堆进行垃圾收集的,所以通常会伴随一次Young GC,但与Full GC不同的是,Mixed GC只能回收部分老年代的Region
  • Full-heap Oriented: Mixed GC collects across the entire heap (usually with a Young GC), but unlike Full GC, it only reclaims some old regions.
  • 内存整理:Mixed GC过程中会将多个老年代Region中仍存活的小对象集中到一个Region中,也就是说Mixed GC会对老年代空间进行内存整理
  • Compaction: Mixed GC consolidates small live objects from multiple old regions into single regions, performing old generation compaction.
  • G1 GC 提供了一种停顿时间预测模型,用户可以通过参数-XX:MaxGCPauseMillis设定每次GC的期望停顿时间
  • G1's pause prediction model allows setting expected pause times via -XX:MaxGCPauseMillis.

并发标记周期 Concurrent Marking Cycle

**Concurrent Marking Cycle Phases:**Concurrent Marking Cycle Phases包括Global Concurrent Marking和Mixed GCs,具体步骤如下图,需要注意的是Global Concurrent Marking不是GC过程,并不会和Mixed GC同时发生,它只负责标记、统计出收集收益高的老年代region。
Concurrent Marking Cycle Phases: Includes Global Concurrent Marking and Mixed GCs. Note: Global Concurrent Marking (not a GC process) solely identifies high-value old regions and doesn't overlap with Mixed GCs.

JAVA基础 - CMS,G1工作模式及调优小结_4.png

  • Initial-mark(初始标记 STW):标记所有能直接可达的根对象,当达到IHOP阈值时并不会直接触发,而是等待下一次Young GC,利用其STW时间完成初始标记。
  • Initial-mark (STW): Marks directly reachable roots. Triggered by waiting for the next Young GC's STW pause when IHOP threshold is reached.
  • Root Region scanning (根区域扫描): 扫描由survivor直接可达老年代区域,并标记这些可达的对象。
  • Root Region Scanning: Scans old regions directly reachable from Survivor spaces and marks reachable objects.
  • Concurrent Marking(并发标记):和应用程序线程并发的执行,从GC Roots开始对堆中的对象标记,标记出各个region中存活的对象
  • Concurrent Marking: Runs concurrently with application threads, marking live objects starting from GC roots across all regions.
  • Remark(重新标记 STW):暂停所有应用线程,重新扫描堆中的对象,标记在并发标记阶段发生变化的对象;
  • Remark (STW): Stops application threads to rescan the heap and finalize marking of objects changed during concurrent marking.
  • Clean(清理(混合STW与并发))Cleanup (Mixed STW & Concurrent):: 
    • STW操作:统计存活对象、完全空闲区域;更新Remembered Sets。
    • STW Operations: Counts live objects, identifies completely free regions, and updates Remembered Sets.
    • 并发操作:把完全空闲的region收集到可分配队列
    • Concurrent Operations: Collects completely free regions into allocation pool.
  • Copying (复制 STW):拷贝整理老年代存活对象的过程,需要暂停应用程序
  • Copying (STW): Evacuates and compacts surviving old generation objects, requiring application pause.

G1的好处 Advantages of G1

  • G1在停顿时间上是可预测的,用户可以设置期望停顿时间,Stop The World时间相对可控
  • Predictable pauses: Users can set target pause times (MaxGCPauseMillis) with better STW control.
  • G1的年轻代和老年代空间并不是固定的,当现有年轻代分区占满时,JVM会分配新的空闲Region加入到年轻代空间,老年代也是如此。还记得在CMS中出现的年轻代空间有大量浪费的情况吗?那将不再是问题。另一方面,由于Talos无法保证每台机器的吞吐完全一致,不同机器的GC压力也是不一样的,该特性使得Talos进程可以根据情况自行调整年轻代和老年代的空间大小,以应对不同的GC压力
  • Dynamic generation sizing: Young/Old generation regions are dynamically adjusted. Solves CMS's young generation space waste issue. Enables adaptive sizing under varying GC pressures across machines.
  • G1 GC的回收过程中有内存整理,理论上不会产生内存碎片!
  • Memory compaction: Eliminates memory fragmentation through object evacuation.

调优总结(G1) Tuning Summary (G1)

JAVA基础 - CMS,G1工作模式及调优小结_5.png

  • 新生代:大部分都是朝生夕死的对象,适当调大新生代内存(G1MaxNewSizePercent),并关注Eden区和两个Survivor区空间利用率(SurvivorRatio)。
  • Young Generation: Most objects are short-lived. Increase young generation size (G1MaxNewSizePercent) and monitor Eden/Survivor utilization (SurvivorRatio).
  • 并发标记周期和Mixed GC:重点关注程序的常驻内存,以此调整并发标记周期的启动时机(InitiatingHeapOccupancyPercent),以及MixGC的启动时机(G1HeapWastePercent)。
  • Concurrent Marking Cycle & Mixed GC: Focus on resident memory size. Tune IHOP (InitiatingHeapOccupancyPercent) for marking cycle triggers and G1HeapWastePercent for Mixed GC initiation.

鸣谢 Acknowledgements

小米Talos GC性能调优实践,大部分基于文章重新整理。
Adapted from Xiaomi Talos GC Performance Tuning Practice


Comment