混合收集器实战中,G1如何根据不同负载动态调整回收Region数量?
- 内容介绍
- 相关推荐
本文共计1030个文字,预计阅读时间需要5分钟。
G1垃圾回收器不是每次回收固定数量的老年代Region,而是基于当前GC目标暂停时间(-XX:MaxGCPauseMillis)、已知的Region回收成本模型以及待回收Region的价值排序,动态决定本轮Mixed GC中老年代Region的回收数量。
关键逻辑在于:G1 先对所有可回收的老年代 Region 按“单位时间回收收益”从高到低排序,再按顺序累加,直到预估总停顿时间逼近目标值。这个过程发生在并发标记完成后的 Evacuation Pause 准备阶段,不占用 STW 时间。
影响 Region 数量选择的三大动态变量
1. 当前老年代可回收 Region 的价值分布
- G1 维护一个按 回收价值 = (Region Size − Live Data) / 预估回收耗时 排序的候选列表
- 价值高的 Region(垃圾多、存活少、引用简单)优先入选;价值低的(如 Humongous 区、RSet 极大、Live Data 接近满)会被延后或跳过
2. 剩余停顿预算与历史预测误差校正
- G1 持续跟踪过去几次 Mixed GC 的实际停顿时间与预测偏差
- 若连续两次超时,会主动降低本轮 CSet 规模(例如减少 1–2 个老年代 Region)
- 若多次远低于目标(如 120ms vs 200ms),则尝试增加 Region 数量以提升吞吐
3. 老年代空间压力与 IHOP 偏离度
- 若当前老年代占用率远高于 IHOP(比如达 65%),G1 会放宽停顿约束,主动多选 Region 加速释放空间,防止触发 Full GC
- 若刚完成一轮 Mixed GC 且老年代占用回落至 35% 以下,G1 可能跳过下一轮或仅选 1–2 个最高价值 Region 做“轻量清理”
实战中可观察和干预的关键信号
看 GC 日志判断是否“保守”或“激进”
- 日志中出现 [GC pause (G1 Evacuation Pause) (mixed) ... 8 regions] 表示本轮选了 8 个老年代 Region
- 若长期稳定在 1–3 个,但 Old Gen 使用率持续攀升 → 可能因 RSet 开销大或 Live Data 估算偏高,导致价值评估失真
- 若频繁出现 Concurrent Cycle was cancelled 或 to-space exhausted → CSet 过小 + 晋升快,需调低 MaxGCPauseMillis 或调高 G1MixedGCCountTarget
常用调优杠杆
- -XX:G1MixedGCCountTarget=8:控制 Mixed GC 总轮数上限(默认 8),值越小,每轮压力越大,Region 数越多
- -XX:G1OldCSetRegionThresholdPercent=10:只考虑 Live Data 占比 ≤10% 的老年代 Region(提高单 Region 回收收益)
- -XX:G1HeapWastePercent=5:当预测浪费内存 ≥5%,提前终止本轮 Mixed GC,避免低效回收
负载变化时的典型响应模式
低负载(请求少、分配慢)
- 年轻代 GC 间隔拉长 → 老年代晋升放缓 → IHOP 不易触发 → Mixed GC 稀疏
- G1 倾向于“精挑细选”,每次只回收 1–2 个最高价值 Region,维持低频、高收益节奏
突发高负载(短时大流量、批量导入)
- Eden 快速填满 → 频繁 YGC → 大量对象晋升 → 老年代占用率快速越过 IHOP
- G1 启动并发标记,并在首轮 Mixed GC 中扩大 CSet(如 12–16 个 Region),甚至跳过部分低价值 Region 的扫描以保停顿
- 若持续高压,可能触发 Allocation Failure in Old Gen,说明 Mixed GC 跟不上晋升速度,需检查对象生命周期或增大堆
稳态高负载(如实时流处理)
- 分配稳定但速率高,Humongous 对象多(如 Netty DirectBuffer)→ RSet 增长快 → Region 价值被低估
- 此时应结合 -Xlog:gc+ergo=debug 观察 Request heap region size 和 Total remembered set memory,必要时增大 G1HeapRegionSize 降低 Region 总数,间接提升单 Region 价值可信度
本文共计1030个文字,预计阅读时间需要5分钟。
G1垃圾回收器不是每次回收固定数量的老年代Region,而是基于当前GC目标暂停时间(-XX:MaxGCPauseMillis)、已知的Region回收成本模型以及待回收Region的价值排序,动态决定本轮Mixed GC中老年代Region的回收数量。
关键逻辑在于:G1 先对所有可回收的老年代 Region 按“单位时间回收收益”从高到低排序,再按顺序累加,直到预估总停顿时间逼近目标值。这个过程发生在并发标记完成后的 Evacuation Pause 准备阶段,不占用 STW 时间。
影响 Region 数量选择的三大动态变量
1. 当前老年代可回收 Region 的价值分布
- G1 维护一个按 回收价值 = (Region Size − Live Data) / 预估回收耗时 排序的候选列表
- 价值高的 Region(垃圾多、存活少、引用简单)优先入选;价值低的(如 Humongous 区、RSet 极大、Live Data 接近满)会被延后或跳过
2. 剩余停顿预算与历史预测误差校正
- G1 持续跟踪过去几次 Mixed GC 的实际停顿时间与预测偏差
- 若连续两次超时,会主动降低本轮 CSet 规模(例如减少 1–2 个老年代 Region)
- 若多次远低于目标(如 120ms vs 200ms),则尝试增加 Region 数量以提升吞吐
3. 老年代空间压力与 IHOP 偏离度
- 若当前老年代占用率远高于 IHOP(比如达 65%),G1 会放宽停顿约束,主动多选 Region 加速释放空间,防止触发 Full GC
- 若刚完成一轮 Mixed GC 且老年代占用回落至 35% 以下,G1 可能跳过下一轮或仅选 1–2 个最高价值 Region 做“轻量清理”
实战中可观察和干预的关键信号
看 GC 日志判断是否“保守”或“激进”
- 日志中出现 [GC pause (G1 Evacuation Pause) (mixed) ... 8 regions] 表示本轮选了 8 个老年代 Region
- 若长期稳定在 1–3 个,但 Old Gen 使用率持续攀升 → 可能因 RSet 开销大或 Live Data 估算偏高,导致价值评估失真
- 若频繁出现 Concurrent Cycle was cancelled 或 to-space exhausted → CSet 过小 + 晋升快,需调低 MaxGCPauseMillis 或调高 G1MixedGCCountTarget
常用调优杠杆
- -XX:G1MixedGCCountTarget=8:控制 Mixed GC 总轮数上限(默认 8),值越小,每轮压力越大,Region 数越多
- -XX:G1OldCSetRegionThresholdPercent=10:只考虑 Live Data 占比 ≤10% 的老年代 Region(提高单 Region 回收收益)
- -XX:G1HeapWastePercent=5:当预测浪费内存 ≥5%,提前终止本轮 Mixed GC,避免低效回收
负载变化时的典型响应模式
低负载(请求少、分配慢)
- 年轻代 GC 间隔拉长 → 老年代晋升放缓 → IHOP 不易触发 → Mixed GC 稀疏
- G1 倾向于“精挑细选”,每次只回收 1–2 个最高价值 Region,维持低频、高收益节奏
突发高负载(短时大流量、批量导入)
- Eden 快速填满 → 频繁 YGC → 大量对象晋升 → 老年代占用率快速越过 IHOP
- G1 启动并发标记,并在首轮 Mixed GC 中扩大 CSet(如 12–16 个 Region),甚至跳过部分低价值 Region 的扫描以保停顿
- 若持续高压,可能触发 Allocation Failure in Old Gen,说明 Mixed GC 跟不上晋升速度,需检查对象生命周期或增大堆
稳态高负载(如实时流处理)
- 分配稳定但速率高,Humongous 对象多(如 Netty DirectBuffer)→ RSet 增长快 → Region 价值被低估
- 此时应结合 -Xlog:gc+ergo=debug 观察 Request heap region size 和 Total remembered set memory,必要时增大 G1HeapRegionSize 降低 Region 总数,间接提升单 Region 价值可信度

