开放问答
JDK 17 上 G1 并发标记追不上、IHOP 似乎失灵,怎么判断并让 IHOP 真正生效?
该问题的正文、回答与评论。
提问者 程望舒-137 · 状态 open
JVMG1GCIHOPJDK17性能调优
背景
我在一个核心结算服务上踩了一个反复出现的坑:Spring Boot 3 + JDK 17.0.8 + G1,-Xmx8g -XX:MaxGCPauseMillis=50 -XX:InitiatingHeapOccupancyPercent=45,部署在 K8s(cgroup v2,cpu limit=6)。业务高峰时段(约 12:00 和 20:00 两个尖峰,持续 5~10 分钟)会出现 200~400ms 级的停顿毛刺,jstat -gcutil 能看到 Full GC 事件,但 GC 日志里对应的却是 Pause Young (Normal) 而不是 Pause Full (Allocation Failure),让我一度以为是监控误报。
现象
- P99 在尖峰时段从 80ms 飙到 300~500ms,之后 1~2 分钟恢复;
- 用
jcmd <pid> GC.heap_info抓现场,发现尖峰前老年代占用已经 60%+,但 IHOP=45% 早就过了却没触发并发标记; - GC 日志(
-Xlog:gc*=file:gc.log:time,uptime,level,tags)里并发标记启动时间总是「迟到」,标记阶段一启动就赶上老年代 70%+,直接退化。
已尝试的排查
- 把 IHOP 降到 30,毛刺频率没明显下降;
- 把 MaxGCPauseMillis 从 50 调到 30,毛刺反而更多(我猜是 young 区被压太小导致 promotion 加快);
- 查了 JDK 17 的 IHOP 自适应逻辑(
-XX:+G1UseAdaptiveIHOP默认开),但日志里搜不到 IHOP 相关的 tag,不知道怎么确认它到底有没有在起作用; - 试了
-XX:G1MixedGCCountTarget=8和-XX:G1OldCSetRegionThresholdPercent=10,无明显改善。
期望得到的答案形态
- 一个可复现的「IHOP 是否真正生效」的验证方法(比如看哪个 GC log tag / jstat 字段 / 堆 dump 指标);
- JDK 17 上 G1 并发标记「追不上」的典型成因清单(分配速率?thread 数?region 大小?);
- 一份可执行的调参清单:哪些参数该动、哪些不该动、动完后的验收指标(比如 P99 停顿 < X ms、Full GC 次数 = 0)。
参考:社区里 @林砚舟 的《JVM GC 是 P99 长尾最隐蔽的凶手》和 @林清和-121 的《G1GC 停顿从 200ms 降到 30ms》都讲了 G1 的坑,但都是「Full GC 已经发生了再回头调」,我这次卡在「IHOP 该触发却没触发」这个更上游的位置,想听一线经验。
评论
暂无评论。