JVM GC相关(三)- GC 调优

前言

在前面两篇文章已经介绍了有关GC的算法以及垃圾回收器的选择,今天这篇来讲下如何针对GC进行JVM调优。

正文

堆大小的调优

一般来说,堆越大越好

  • 降低GC频率,但过大可能会增加单次GC的时间
  • 对象更有可能成为垃圾

受硬件和操作系统限制

  • 32位操作系统单个进程的最大可用内存为2G,64位无限制
  • 小心平衡New和Old的比例

参数

  • -Xms=1024MB:堆的最小值
  • -Xmx=1024MB:堆的最大值
  • 堆每次调整都会触发一次Full GC (避免频繁调整,可以设置 -Xms=-Xmx)

-Xms==-Xmx?

  • 设置-Xms为堆的预期大小
    • 堆调整的代价很大
  • 如果内存允许,设置-Xmx为一个比-Xms更大的数值
    • 以防万一
    • 也许系统负载比你想的要重
    • 随着时间的推移,数据量越来越大
    • ……
  • 进行一次Full GC & 堆调整总比发生OOM & 宕机要好

新生代调优-大小

  • 增加Eden的大小会
    • 降低minor GC的频率
    • 但不一定会增大minor GC的时间
      • minor GC的耗时和要拷贝的对象数量,即存活对象多少成正比
  • 参数
    • -XX:NewSize=1024MB : 新生代初始大小
    • -XX:MaxNewSize=1024MB : 新生代最大值
    • -XX:NewRatio=m : New 和 Old 的比值
    • -Xmn=1024MB : 新生代大小
    • 出于性能考虑,一般使用-Xmn来固定新生代大小

新生代调优-晋升

  • 尽可能地让对象待在survivor中,使之在新生代被回收
    • 减少晋升到老年代的对象
    • 降低老年代 GC 的频率
  • 但是同时,避免长时间存活的对象在survivor间不必要的拷贝
    • 增加minor GC不必要的开销
  • 不容易找到平衡点
    • 原则上:better copy more,than promote more
  • -XX:SurvivorRatio=m : Eden 和 Survivor 的比值
  • 对象晋升年龄的阀值:Tenuring Threshold
    • 年龄标志位age, 每熬过一轮GC对象年龄加1
    • Serial Copying 和 ParNew 每次minor GC后重新计算Tenuring Threshold的规则:
      • 参数-XX:TargetSurvivorRatio=n : minor GC 后Survivor预期被占用的比例
      • 计算Desired Survivor Size = Survivor大小 * TargetSurvivorRatio
      • 统计存活对象的年龄,若在某个年龄上的对象总大小 > Desired Survivor Size, 则 TenuringThreshold = min(该年龄,MaxTenuringThreshold)
      • 否则 TenuringThreshold = MaxTenuringThreshold
      • 下次 minor GC的阀值就以此为准
  • 查看每次 minor GC 后年龄的分部和计算出来的 TenuringThreshold:
    • -XX:+PrintTenuringDistribution

老年代调优

  • 尽可能地调优新生代
    • 尤其要注意 CMS 中的 Promotion
      • free list
      • 更容易出现内存碎片
  • (对CMS)在不紧要的时间段手动进行Full GC
    • 清理堆,压缩,减少内存碎片
  • 大小的平衡
    • 太大 —— 单次GC时间长;
    • 太小 —— GC频率高
  • 硬件优化
    • 加CPU
  • 程序优化,避免无用对象浪费Old空间
    • 去掉不必要的缓存
    • oracle 10g驱动时preparedstatement cache太大
发布了29 篇原创文章 · 获赞 9 · 访问量 9956

猜你喜欢

转载自blog.csdn.net/weixin_42669785/article/details/90517477