CMS(Concurrent Mark Sweep)吞吐量优于G1,主要源于其设计定位与执行机制,CMS以吞吐量为核心,采用并发标记与清除算法,大部分回收工作与应用线程并发执行,仅短暂的初始标记和重新标记阶段需STW(Stop-The-World),显著减少停顿时间,提升CPU利用率,而G1虽也支持并发,但通过Region划分堆内存,优先回收价值最大的Region,回收过程中涉及更复杂的复制整理(Evacuation),额外内存分配与复制开销较大,且在并发失败时易触发Full GC,反而降低吞吐量,CMS的标记清除逻辑相对简单,而G1的平衡性设计兼顾低延迟,牺牲了部分吞吐量优势。
CMS与G1:为何CMS在吞吐量表现上更胜一筹?
在Java虚拟机(JVM)的垃圾回收(GC)领域,吞吐量(Throughput)与停顿时间(Pause Time)是衡量GC性能的两大核心指标。**吞吐量**指单位时间内应用程序处理业务逻辑的时间占比(计算公式:吞吐量 = 应用程序运行时间 / (应用程序运行时间 + GC时间)),高吞吐量意味着GC开销小,CPU资源能更高效地服务于业务逻辑;**停顿时间**则指GC过程中应用线程暂停的持续时间,低停顿时间对提升用户体验至关重要。
CMS(Concurrent Mark Sweep)与G1(Garbage-First)是JVM中两款里程碑式的垃圾回收器:CMS以**极致低停顿**为首要目标,专注于最小化应用暂停时间;G1则旨在**平衡吞吐量与停顿时间**,通过其创新的“可预测停顿模型”成为大内存场景(如6GB以上)的主流选择,在特定应用场景下,CMS的吞吐量表现反而优于G1,本文将从设计理念、算法实现、资源开销等维度,深入剖析CMS吞吐量优势背后的技术逻辑。
吞吐量的核心:GC开销占比与业务资源竞争
理解CMS吞吐量优势的关键在于把握吞吐量的本质——**GC执行过程中消耗的CPU资源越少,应用程序能占用的CPU资源就越多,单位时间内处理的业务量自然越大**,CMS与G1在设计理念上的根本差异,直接决定了它们在GC资源分配策略上的不同取向。
CMS的设计初心:最大化应用运行时间
CMS是一款**以应用为中心**的回收器,其核心设计哲学是**最大限度减少GC对应用线程的干扰**,它通过并发执行机制,让GC线程与应用线程“并行工作”,CMS的运作流程包含四个关键阶段:
- 初始标记(Initial Mark):短暂的STW(Stop-The-World,即全局暂停),仅标记与GC Roots直接关联的对象;
- 并发标记(Concurrent Mark):与应用线程并行执行,遍历并标记所有存活对象;
- 重新标记(Remark):短暂的STW,用于修正并发标记期间因应用线程运行导致对象状态变化带来的标记偏差;
- 并发清除(Concurrent Sweep):与应用线程并行执行,直接清除被标记为垃圾的对象。
在整个流程中,**并发标记与并发清除阶段合计占比超过90%**,且这两阶段均与应用线程并行运行,几乎不阻塞业务逻辑,这意味着在CMS运行期间,CPU资源绝大部分被应用程序占用,GC开销极低,从而直接推高了整体吞吐量。
G1的设计平衡:为“可预测停顿”牺牲部分吞吐量
G1的设计目标是**在可预测的停顿时间窗口内,实现吞吐量与停顿时间的平衡**,尤其针对大堆内存(如6GB以上)场景,它通过“Region分区”和“可预测停顿模型”有效解决了CMS的内存碎片问题。“平衡”的本质往往伴随着“妥协”——为了实现停顿时间的精准控制,G1不得不引入更复杂的计算逻辑和更高的资源开销。
G1的核心机制包括:
- Region分区:将堆内存划分为多个固定大小(如1MB-32MB)的独立Region,每个Region动态扮演Eden、Survivor或Old角色;
- 优先级回收:基于“回收价值”(垃圾占比/预估回收时间)智能选择回收哪些Region,优先回收“垃圾多、回收快”的高价值区域;
- 全局并发标记:借鉴了CMS的并发思想,但引入了SATB(Snapshot-At-The-Beginning)算法确保并发标记期间对象引用变化的准确性;
- 混合回收:在并发标记完成后,分阶段回收Eden、Survivor及Old Region,并可能执行对象移动(整理)以消除碎片。
相较于CMS,G1的GC流程显著复杂化:混合回收阶段需同时处理多个Region,且涉及对象移动(整理),这大幅增加了单次GC的计算开销;为实现“可预测停顿”,G1需持续跟踪各Region的回收成本并进行精细调度,这种“精细化管理”本身也消耗可观的CPU资源,在同等业务负载下,G1的GC总开销通常高于CMS,导致应用程序可用的CPU资源减少,其吞吐量自然低于CMS。
算法与实现:CMS的“轻量级”与G1的“重量级”
除了设计理念,GC算法本身的实现细节(如是否需要对象整理、写屏障开销等)是影响吞吐量的关键因素。
标记-清除 vs 标记-整理:CMS的“零成本”清除
CMS采用经典的**标记-清除(Mark-Sweep)**算法,在并发清除阶段,它仅需遍历堆空间,直接清除被标记为垃圾的对象,**无需进行对象移动或内存整理**,这种“原地清除”方式带来了两大优势:
- 零整理开销:避免了对象移动带来的巨大计算成本(如更新引用、数据拷贝),显著降低了单次GC的CPU消耗。
- 最小化写屏障干扰:对象移动通常需要启用写屏障(Write Barrier)来跟踪引用变化,而CMS的清除阶段无需此机制,减少了额外的运行时开销。
CMS的清除阶段在资源消耗上极为“轻量级”,是其高吞吐量的重要基石。
G1的混合回收:对象移动带来的吞吐量代价
G1的核心回收策略是**混合回收(Mixed Collection)**,它不仅回收Eden和Survivor区,更关键的是回收Old区,为了解决内存碎片问题,G1在回收Old Region时,**会执行对象移动(整理)操作**,将存活对象压缩到连续的Region空间中,这带来了显著的吞吐量影响: