JVM-GC调优

作者: 石头耳东 | 来源:发表于2022-05-07 22:05 被阅读0次

    零、本文纲要

    一、 GC调优基本思路
    二、 新生代内存调优
    三、 老年代内存调优
    四、 GC调优案例

    官方GC调优指南

      1. 查看虚拟机运行参数

    命令:"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" -XX:+PrintFlagsFinal -version | findstr "GC"

    部分JDK8的JVM默认配置如下:

    uintx GCTimeRatio                               = 99                                  {product}
    uintx MaxGCPauseMillis                          = 4294967295                          {product}
    uintx ParallelGCThreads                         = 13                                  {product}
     bool ScavengeBeforeFullGC                      = true                                {product}
     bool UseParallelGC                            := true                                {product}
     bool UseParallelOldGC                          = true                                {product}
    

    一、 GC调优基本思路

    1. 调优领域

    内存
    锁竞争
    CPU占用
    I/O

    2. 目标确定

    低延迟/高吞吐
    低延迟:CMS、G1、ZGC
    高吞吐:ParallelGC

    3. 减少GC

    查看Full GC前后的内存占用

    • ① 数据量是不是太多?

    数据库查询limit

    • ② 数据表示是否太臃肿?

    对象图
    数据类型选择

    • ③ 是否存在内存泄漏?

    软引用、弱引用
    第三方缓存实现

    二、 新生代内存调优

    1. 新生代特点

    ① new操作内存分配廉价(TLAB thread-local allocation buffer)
    ② 新生代垃圾回收采用复制算法,回收代价低
    ③ 大部分对象用过即可回收
    ④ Minor GC的时间远低于Full GC

    2. 新生代调优方法

    • ① 内存大小调整

    命令:-Xmn size

    Oracle建议新生代大小占整个堆空间25%-50%。

    • ② 新生代调优参考

    Ⅰ 新生代能容纳所有[并发量 * (请求 - 响应)]的数据

    Ⅱ 幸存区大到能保留[当前活跃对象 + 需要晋升对象]的数据

    Ⅲ 晋升阈值配置得当,让长时间存货对象尽快晋升
    -XX:+PrintTenuringDistribution:通过打印幸存区年龄空间数据,预估合理阈值
    -XX:MaxTenuringThreshold=threshold:根据上述阈值,设置使用

    三、 老年代内存调优

    1. CMS老年代调优

    注意:以CMS为例

    • ① CMS老年代内存越大越好

    避免浮动垃圾过多,进而引起并发清除失败,退化为SerialOld。

    • ② 如果Full GC频繁,则先尝试调优新生代

    • ③ 观察发生Full GC时老年代内存占用,将老年代内存预设调大1/4~1/3

    命令:-XX:CMSInitiatingOccupancyFraction=percent:当老年代内存使用占到老年代内存空间的68%(默认)触发Full GC。可以设置为75-80%。

    四、 GC调优案例

    案例一、 Full GC和Minor GC频繁

    ① 增大新生代内存大小
    ② 增大幸存区空间,以及晋升阈值

    案例二、 请求高峰期发生Full GC,单次暂停时间特别长(CMS)

    • ① 确认哪个阶段时间较长:初始标记、并发标记、重新标记、并发清除

    Ⅰ 初始标记:STW,标记GC Roots的直接关联对象
    Ⅱ 并发标记:没有STW,使用GC Roots Tracing算法,进行跟踪标记。并发标记过程中产生变动的对象会放入一个队列中,供重新标记过程遍历使用。
    Ⅲ 重新标记:STW,由于并发标记其他线程不暂停,可能产生新垃圾,重新标记
    Ⅳ 标记清除:没有STW

    • ② 响应时间优先优化

    命令:-XX:+CMSScavengeBeforeRemark

    在重新标记之前,进行一次新生代的垃圾回收。可以减少重新标记的对象,提升效率,优化响应。

    案例三、 老年代充裕情况下,发生Full GC(1.7)

    永久代(元空间)空间不足导致的Full GC

    五、结尾

    以上即为JVM-GC调优的基础内容,感谢阅读。

    相关文章

      网友评论

        本文标题:JVM-GC调优

        本文链接:https://www.haomeiwen.com/subject/ifqfurtx.html