核心是通过统一基线压测、时间锚点日志、gcviewer导出结构化事件、绘制三类关键曲线,横向对比不同gc配置在相同流量下的停顿稳定性与吞吐表现。

核心思路是:在相同业务流量和资源约束下,让不同 GC 配置跑同一轮压测,再用统一工具解析日志,横向比对关键耗时指标的分布与趋势。
一、压测前必须统一基线
确保对比公平,所有测试实例需满足:
- JVM 启动参数除 GC 相关项外完全一致(如 -Xms/-Xmx、-XX:MaxDirectMemorySize、线程池配置等)
- 压测脚本完全相同:QPS 模式(恒定并发 or 阶梯上升)、请求路径、数据构造逻辑、warmup 时长(建议 ≥3 分钟)
- 系统环境隔离:单实例独占 CPU 核心、内存不超售、禁用 swap、关闭 transparent_hugepage
- GC 日志格式强制对齐:统一用 JDK 8 兼容格式(即使 JDK 17 也加 -XX:+PrintGCDetails -XX:+PrintGCDateStamps),避免 GCViewer 解析偏差
二、日志采集要带时间锚点
每轮压测开始前记录准确起始时间(如 date +%s.%N),并在 JVM 启动时加 -XX:+PrintGCDateStamps。这样导出的每条 GC 记录都含真实时间戳,后续才能对齐多组日志的时间轴。
推荐日志参数组合:
- -Xloggc:gc-profile-name.log(如 gc-g1-200ms.log)
- -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 -XX:GCLogFileSize=50M
- 禁用 -Xlog 新格式,防止 GCViewer 丢事件
三、用 GCViewer 导出结构化耗时序列
不是看 Summary 页的平均值,而是导出原始事件流:
- 打开 GCViewer → File → Open → 选对应 gc-*.log
- 点击 File → Export → CSV,勾选 Timestamp, Duration, Type, GC Cause
- 导出后得到每行一条 GC 事件:开始时间、停顿毫秒数、是 Young/Mixed/Full、触发原因(如 Allocation Failure / Metadata GC Threshold)
注意:Duration 是 STW 实际耗时,已自动合并 G1 的 Evacuation Pause + Mixed Pause 子阶段,比手动加总更准。
四、画曲线时聚焦三类关键图
用 Python(Pandas + Matplotlib)或 Grafana 对 CSV 做窗口聚合,建议窗口粒度为 10 秒:
- 停顿时间热力图:横轴时间、纵轴 Duration,用颜色深浅表示频次密度——快速识别某段是否突发长停顿
- 吞吐量滚动曲线:每 10 秒计算 1 − (该窗口内所有 Duration 总和 ÷ 10000ms),画成折线——直观看出哪组配置在压测中段开始掉吞吐
- GC 类型占比堆叠图:统计 Young/Mixed/Full 出现次数及总耗时占比——若某组 Full GC 频次高,说明老年代晋升失控,不是调参能解决的
真正有价值的结论,往往藏在「相同吞吐量下,谁的停顿更平稳」「同等 P95 响应下,谁的 GC 耗时波动更小」这类对比里,而不是单纯比平均值。










