diff --git a/文档/20250326-G1CG调优.md b/文档/20250326-G1CG调优.md index 7782be8..d683c2b 100644 --- a/文档/20250326-G1CG调优.md +++ b/文档/20250326-G1CG调优.md @@ -1,4 +1,36 @@ # 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 @@ -43,10 +75,138 @@ java -server --spring.config.location=/app/config/bootstrap.yml ``` ### 参数说明 -- https://www.cnblogs.com/yu007/p/17900844.html +- https://www.cnblogs.com/yu007/p/17900844.html + - 容器环境替代 `-Xmx -Xms`: - ```shell -XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=70.0 - ``` \ No newline at end of file + ``` + +#### 详细说明 +```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以下,此时建议:精简下应用服务(减少实例的产生)、升级高版本jdk(17)、做好压测、长期关注。 +-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个region,eden区对应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个jvm,cpu个数 / 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时的。 + +``` \ No newline at end of file