keyfil/文档/20250326-G1CG调优.md
liuxiaohua a586974c87
All checks were successful
Publish to Confluence / confluence (push) Successful in 33s
[2025-04-09] 完善GC文档
2025-04-09 10:09:34 +08:00

212 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# G1CG调优
## 建议
### 宿主机G1配置
```shell
java -jar -Xmx4096m -Xms4096m
-XX:+UseG1GC -XX:MaxGCPauseMillis=50
-XX:G1ReservePercent=10 -XX:ConcGCThreads=2
-XX:ParallelGCThreads=5 -XX:G1HeapRegionSize=2m
-XX:MaxTenuringThreshold=14 -XX:SurvivorRatio=8
-XX:G1HeapRegionSize=1M -XX:InitiatingHeapOccupancyPercent=40 -XX:+UseStringDeduplication
```
- -XX:G1HeapRegionSize=2m: Region的大小配置可以增大Region大小配置来减少大对象占用的Region数
- -XX:MaxGCPauseMillis=50: GC停顿时间
- -XX:InitiatingHeapOccupancyPercent=40: 老年代Region触发混合GC的占比默认值是45也就是说老年代占据了堆内存45%的Region的时会触发混合GC。该值一般不需要调整这样可以让JVM内存占用维持在50%左右
- -XX:+UseStringDeduplication: 开启字符串去重 G1回收器生效
### 容器G1配置
```shell
java -jar -XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=70.0
-XX:+UseG1GC -XX:MaxGCPauseMillis=50
-XX:G1ReservePercent=10 -XX:ConcGCThreads=2
-XX:ParallelGCThreads=5 -XX:G1HeapRegionSize=2m
-XX:MaxTenuringThreshold=14 -XX:SurvivorRatio=8
-XX:G1HeapRegionSize=1M -XX:InitiatingHeapOccupancyPercent=40 -XX:+UseStringDeduplication
```
### 宿主机ZGC配置
```shell
java -jar --add-opens=java.base/java.lang=ALL-UNNAMED -Xms4096m -Xmx4096m -XX:ReservedCodeCacheSize=256m -XX:InitialCodeCacheSize=256m -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ConcGCThreads=1 -XX:ParallelGCThreads=3 -XX:ZCollectionInterval=60 -XX:ZAllocationSpikeTolerance=4 -XX:+UnlockDiagnosticVMOptions -XX:-ZProactive -Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/opt/gc-%t.log:time,tid,tags:filecount=5,filesize=50m
```
## 参考
- https://cloud.tencent.com/developer/article/1518229
- -XX:+UseG1GC -XX:+UseStringDeduplication
- -Xms2g -Xmx2g
-XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=1m -XX:G1MixedGCCountTarget=10
-Xloggc:/data/server/${app}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime
- -Xms2g -Xmx2g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=100 // 调大停顿时间
-XX:G1HeapRegionSize=2M # 调大region的大小来减少大对象占用的region数
-XX:MaxTenuringThreshold=5
-XX:InitiatingHeapOccupancyPercent=40 #手动设置IHOP
-XX:ConcGCThreads=4 //当前核心数的一半
-XX:+UseStringDeduplication
-XX:AutoBoxCacheMax=20000
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
-XX:+PrintPromotionFailure
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
-Xlog:gc*:./gc-myapp.log
-XX:+DisableExplicitGC //禁止显示手动GC如果系统使用了堆外内存就不要禁用
-XX:G1MixedGCCountTarget=10 // 把old区的回收分布到更多次GC当中
- https://zhuanlan.zhihu.com/p/444564414
## 启动参数
```shell
java -server
-XX:+UseContainerSupport
-XX:InitialRAMPercentage=70.0
-XX:MaxRAMPercentage=70.0
-XX:+UseG1GC
-XX:MaxGCPauseMillis=20
-XX:G1HeapRegionSize=1M
-XX:InitiatingHeapOccupancyPercent=45
-XX:+UseStringDeduplication
-Ddruid.mysql.usePingMethod=false
-javaagent:/app/skywalking-agent/skywalking-agent.jar
-Dskywalking.agent.service_name=qifu-saas-wms-prod
-Dskywalking.collector.backend_service=oap.qifu.svc:11800
-jar
-javaagent:/app/jmx_prometheus_javaagent-0.20.0.jar=8088:/app/jmx_exporter.yaml
/app/qifu-saas-wms-service-1.0.13.jar
--spring.config.location=/app/config/bootstrap.yml
```
### 参数说明
- https://www.cnblogs.com/yu007/p/17900844.html
- 容器环境替代 `-Xmx -Xms`:
- ```shell
-XX:+UseContainerSupport
-XX:InitialRAMPercentage=70.0
-XX:MaxRAMPercentage=70.0
```
#### 详细说明
```shell
#- 使用G1垃圾收集器在低延迟和高吞吐间寻找平衡可以调整最大停止时间设置新生代大小来提高吞吐量
-XX:+UseG1GC
#- 堆内存示例设置最大最小值为4g对于G1一般建议2g以上。注意设定Xms=Xmx防止发生扩容、缩容
-Xms4g -Xmx4g
#- 配置元空间初始256m、最大256m。不配置的话元空间会不受限地占用物理机内存
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m
#- 设置最大暂停时间默认200ms。G1收集回收器将堆进行分区划分为一个个的区域每次收集的时候只收集其中几个区域以此来控制垃圾回收产生一次停顿时间。
#- 暂停时间只是一个目标并不能总是得到满足G1会逐步调整到最佳状态。但若暂停时间设置的太短就会导致出现G1跟不上垃圾产生的速度最终退化成Full GC。
#- 在极端环境如要求业务接口需要快速返回结果下可尝试设置20ms以下此时建议精简下应用服务减少实例的产生、升级高版本jdk17、做好压测、长期关注。
-XX:MaxGCPauseMillis=100
#- 指定Region大小必须是2次幂最大是32m具体取值有1MB、2MB、4MB、8MB、16MB、32MB。注意当对象占用内存超过Region的一半时将被视为大对象被分配到Humongous区域
#- 可以预估应用服务的对象大小确定Region大小。如果没有大对象的场景则可尝试配置2m、1m使单个Region能被快速回收
#- 该配置非必填不声明时Region大小等于堆大小除以2048
-XX:G1HeapRegionSize=2m
#- 针对混合回收回收的参数:混合回收不仅针对老年代,还有新生代和大对象
#- 老年代Region触发混合GC的占比默认值是45也就是说老年代占据了堆内存45%的Region的时会触发混合GC。该值一般不需要调整这样可以让JVM内存占用维持在50%左右
-XX:InitiatingHeapOccupancyPercent=45
#- 混合回收阶段会执行8次默认值一次只回收掉部分Region然后系统继续运行一小段时间之后再继续混合回收重复8轮。混合回收通过间断操作可以把每次的回收时间控制在指定的停顿时间之内最终也达到了垃圾清理的效果。
-XX:G1MixedGCCountTarget=8
#- 混合回收整理出来的空闲空间占heap的5%时(默认值),终止本次回收
-XX:G1HeapWastePercent=5
#- 如果一个Region中的存活对象大于Region大小的85%的话默认值就不去回收这个Region
-XX:G1MixedGCLiveThresholdPercent=85
#- 设置新生代大小默认5%默认最大60%。在运行过程中JVM会不停的给年轻代增加更多的Region但是最多新生代的占比不会超过G1MaxNewSizePercent值
#- 年轻代中的Eden和Survivor对应的region也跟之前 一样默认8:1:1例如年轻代现在有1000个regioneden区对应800个s0对应100个s1对应 100个
#- 理论上不同的应用、不同的CPU硬件资源都会有不同的最优值但区别不会太大。通过实践总结调整该值的收益远不如调整其他参数如上面提到的几个
-XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60
#- gc日志打印到执行日志文件
-Xloggc:/data/server/${app}/gc.log
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime
#- 可以生成更详细的Survivor空间占用日志开发环境调试用
-XX:+PrintAdaptiveSizePolicy
#- 在控制台输出GC情况一般是本地调试用。上线后是后台运行不关注控制台日志
-verbose:gc
#- 开启远程debug开发环境、测试环境可考虑配置
-Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n
#- spring相关指定加载配置文件
--spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,file:/home/mall-job/conf/
```
#### 其余参数
```shell
#- 新时代E区和S区比例默认8:1:1。一般来说不需要调整
-XX:SurvivorRatio=8
#- 异常场景相关参数
-XX:ErrorFile=文件 #- 设置错误日志路径 -XX:ErrorFile=./hs_err_pid%p.log %p为当前进程号
-XX:OnError=命令 #- 错误发生时执行命令 -XX:OnError="gcore %p;dbx - %p"
-XX:OnOutOfMemoryError=命令 #- 内存溢出时执行命令
-XX:MaxDirectMemorySize=size #- 设置直接内存最大值 -XX:MaxDirectMemorySize=100m 默认为0 当直接内存达到设置的最大值会FullGC
-XX:ObjectAlignmentInBytes=alignment #- 设置java对象的内存对齐默认是8字节
-XX:ThreadStackSize #- 设置线程栈大小 -XX:ThreadStackSize=1m = -Xss
-XX:-UseBiasedLocking #- 禁用偏向锁 默认开启,不禁用 如果使用的是大量的没有竞争的同步,使用偏向锁会提升性能
-XX:-UseCompressedOops #- 禁用压缩指针堆内存小于32G时默认开启 开启后对象引用是32位而不是64位可以提升性能。只有64位的jvm才生效
-XX:+DoEscapeAnalysis #- 开启逃逸分析 默认开启
-XX:+Inline #- 开启方法内联 默认开启
-XX:InlineSmallCode=大小 #- 设置应内联的已编译方法的最大代码大小,只有小于此数值的才会内联 默认1000字节
-XX:MaxInlineSize=大小 #- 设置要内联方法的最大字节码大小 默认35字节
-XX:+OptimizeStringConcat #- 开启字符串连接优化 默认开启
-XX:+PrintInlining #- 打印方法内联 默认关闭,需和-XX:+UnlockDiagnosticVMOptions 一起使用
-XX:-TieredCompilation #- 关闭分层编译 默认开启
-XX:+HeapDumpOnOutOfMemoryError #- OOM时堆内存dump到当前目录
-XX:HeapDumpPath=路径 #- 设置堆内存dump的路径 -XX:HeapDumpPath=/var/java_pid%p.hprof
-XX:+UnlockDiagnosticVMOptions #- 开启jvm诊断功能选项
#- 垃圾回收相关参数
-XX:+AggressiveHeap #开启堆最优化设置 默认关闭
-XX:+CMSClassUnloadingEnabled #当使用CMS垃圾收集器时允许类卸载 默认开启
-XX:CMSExpAvgFactor=percent #指定垃圾收集消耗的时间百分比 默认这个数是25%就是25
-XX:CMSInitiatingOccupancyFraction=percent #设置CMS回收开始的老年代百分比 默认-1任何的负值表示会使用-XX:CMSTriggerRatio选项来定义这个百分比数
-XX:+CMSScavengeBeforeRemark #- 在CMS重新标记之前执行ygc操作 默认关闭 在remark时间过长时可以开启开启减少remark的STW时间
-XX:CMSTriggerRatio=percent #- 设置CMS开始的百分比 默认80((100 - MinHeapFreeRatio) + (double)( CMSTriggerRatio * MinHeapFreeRatio) / 100.0) / 100.0=92%
-XX:+UseCMSCompactAtFullCollection #- 在FULL GC的时候对年老代的压缩
-XX:CMSFullGCsBeforeCompaction=0 #- 上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩,
-XX:MinHeapFreeRatio=percent #- GC之后堆内存最小剩余百分比如果小于此值则自动扩容 默认40%
-XX:MaxHeapFreeRatio=percent #- GC之后堆内存最大剩余百分比如果小于此值则自动缩容 默认70%
-XX:ParallelGCThreads=threads #- 设置Parallel GC的线程数 默认根据cpu个数<=8,则使用8个>8个3+5N/81台服务器只有1个jvm时使用默认值较好如果有n个jvmcpu个数 / n比较合适
-XX:ConcGCThreads=个数 #- 并发GC的线程数 默认值取决于cpu个数 ConcGCThreads = (ParallelGCThreads + 3)/4
-XX:+DisableExplicitGC #- 使System.gc()显式gc失效 默认不开启,
-XX:G1HeapRegionSize=size #- 当使用G1收集器时设置java堆被分割的region大小 1M~32M默认根据堆内存最优化设置
-XX:+G1PrintHeapRegions #- 打印G1收集器收集的区域 默认关闭
-XX:G1ReservePercent=percent #- 设置堆内存保留大小,以防晋升失败 0~50 默认10%
-XX:InitialHeapSize=size #- 堆初始大小 =-Xms
-XX:MaxHeapSize=size #- 堆最大大小 =-Xmx
-XX:InitialSurvivorRatio=ratio #- 设置伊甸园区和幸存区初始比例 默认为8:1
-XX:SurvivorRatio=ratio #- 设置伊甸园区和幸存区比例 默认为8:1 8:1:1
-XX:TargetSurvivorRatio #- YGC之后幸存区期望百分比 默认 50%
-XX:InitiatingHeapOccupancyPercent=percent #- 堆占用达到多少开始并发垃圾回收 只有并发垃圾回收器生效
-XX:MaxGCPauseMillis=time #- GC最大暂停时间 ms 默认没有最大暂停时间
-XX:MetaspaceSize=size #- 元空间多次扩容后超过此值就会full gc 默认大约20M 元空间使用本地内存。 尽量设置足够避免因为这个区域内存不够引发Full GC
-XX:MaxMetaspaceSize=size #- 设置元空间最大大小 默认不限制 建议和MetaspaceSize一样大一般256M
-XX:NewSize=size #- 设置年轻代初始大小 建议年轻代占堆大小的1/4 ~ 1/2
-XX:MaxNewSize=size #- 设置年轻代最大大小 默认根据最大效能分配
-XX:MaxTenuringThreshold=threshold #- 最大晋升年龄,从年轻代到老年代 默认15 - 并行回收器 6 - CMS
-XX:NewRatio=ratio #- 设置老年代和新生代比例 默认2 老年代 : (伊甸园 + 2个幸存区
-XX:+PrintGC #- 打印GC信息 默认关闭
-XX:+PrintGCDetails #- 打印GC详细信息 默认关闭
-XX:+PrintTenuringDistribution #- 打印晋升分配
-XX:+ScavengeBeforeFullGC #- Full gc之前先ygc 默认开启
-XX:+UseTLAB #- 年轻代使用线程局部缓存 默认开启 效率高
-XX:TLABSize=size #- 设置初始化thread-local allocation buffer (TLAB)大小
-XX:+UseAdaptiveSizePolicy #- JDK 1.8 默认使用 UseParallelGC 垃圾回收器,该垃圾回收器默认启动了 AdaptiveSizePolicy
-XX:+UseParallelGC #- 年轻代使用并行回收器
-XX:+UseParallelOldGC #- 老年代使用并行回收器
-XX:+UseParNewGC #- 为配置CMS年轻代使用ParNew回收器CMS会默认开启
-XX:+UseConcMarkSweepGC #- 使用CMS回收器
-XX:+UseG1GC #- 使用G1回收器
-XX:+UseGCOverheadLimit #- 限制GC的运行时间通过统计GC时间来预测是否要OOM了提前抛出异常防止OOM发生 并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作
-XX:+UseStringDeduplication #- 开启字符串去重 G1回收器生效
-XX:AutoBoxCacheMax=20000 #- 加大Integer Cache
-XX:+PrintPromotionFailure #- 知道是多大的新生代对象晋升到老生代失败从而引发Full GC时的。
```