GC优化

当Java程序性能达不到既定目标,且其他优化手段都已经穷尽时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化。但GC算法复杂,影响GC性能的参数众多,且参数调整又依赖于应用各自的特点,这些因素很大程度上增加了GC优化的难度。即便如此,GC调优也不是无章可循,仍然有一些通用的思考方法

JVM基础

内存结构

主流虚拟机Hotspot VM将内存划分为不同的物理区,就是“分代”思想的体现。如图所示,JVM内存主要由新生代、老年代、永久代构成。

常见垃圾回收器

不同的垃圾回收器,适用于不同的场景。常用的垃圾回收器:

  • 串行(Serial)回收器是单线程的一个回收器,简单、易实现、效率高。
  • 并行(ParNew)回收器是Serial的多线程版,可以充分的利用CPU资源,减少回收的时间。
  • 吞吐量优先(Parallel Scavenge)回收器,侧重于吞吐量的控制。
  • 并发标记清除(CMS,Concurrent Mark Sweep)回收器是一种以获取最短回收停顿时间为目标的回收器,该回收器是基于“标记-清除”算法实现的。

参数基本策略

活跃数据的大小是指,应用程序稳定运行时长期存活对象在堆中占用的空间大小,也就是Full GC后堆中老年代占用空间的大小。

空间 倍数
总大小 3-4 倍活跃数据的大小
新生代 1-1.5 活跃数据的大小
老年代 2-3 倍活跃数据的大小
永久代 1.2-1.5 倍Full GC后的永久代空间占用

优化步骤

GC优化一般步骤可以概括为:确定目标、优化参数、验收结果。

确定目标

明确应用程序的系统需求是性能优化的基础,系统的需求是指应用程序运行时某方面的要求,譬如: - 高可用,可用性达到几个9。 - 低延迟,请求必须多少毫秒内完成响应。 - 高吞吐,每秒完成多少次事务。

优化

通过收集GC信息,结合系统需求,确定优化方案,例如选用合适的GC回收器、重新设置内存比例、调整JVM参数等。

进行调整后,将不同的优化方案分别应用到多台机器上,然后比较这些机器上GC的性能差异,有针对性的做出选择,再通过不断的试验和观察,找到最合适的参数。

XX:MaxGCPauseMillis=500

使用G1将会受益

超过50%的Java堆被实时数据占用。
对象分配率或提升率差异很大。
该应用程序正在经历不希望的长时间垃圾收集或压缩暂停(长于0.5到1秒)。

设想验证:

  1. Java程序可见的不是容器资源,是宿主机的资源。在JDK191后fix,更新JDK验证后,不是这个问题
  2. 各种引用导致YGC耗时

    1. 套接字是Final引用,Final引用GC比较耗时,dubbo 是长连接,这样的话还好
    2. 不过确实在出现的问题的时候,有大量的Dubbo请求,仍然作为一个怀疑点
  3. 某个时间点请求的数据量很大,如果第一次YGC过程中无法足够快地将对象从年轻一代移动到老一代,因为旧一代没有足够的内存。则需要等safepoint,其他GC也会出现这样情况,而safepoint 如果是一个锁,那么最终所有的GC需都暂停,此过程将会是一个长耗时的过程

    1. 此过程尝试使用G1GC,JDK9以后默认的。官方推荐使用heap大于4G的应用(尝试中)
    2. 增大或减少eden 区大小(尝试中)

9111验证跟踪

  1. 未切线上流量,使用大问句压测线上使用G1GC容器

    1. 容器应用未挂
    2. CPU 8核满负荷
    3. GC日志分析,YGC<1.58秒,FGC<5秒
  2. 使用G1GC容器切百分之十线上流量

    1. 当天没有大问句,未出现问题和异常
  3. 使用G1GC容器切百分之二十线上流量

    1. 容器出问题

      1. 2个pod错误量突出高
      2. 原因 所在的CPU型号比较老,性能较差
      3. 运维切下线百分之十
    2. 一台datacore请求慢

      1. 无特别情况,日志看不出异常,仅仅表现出慢
      2. 原因 所在物理机load过高
  4. 使用G1GC容器切百分之十线上流量

    1. 对大问句做限制,但未出现大问句
    2. 强化容器CPU调度策略
    3. 容器指标各项正常
  5. 使用G1GC容器切百分之二十线上流量

    1. 大问句受限
    2. 容器指标稳健

问题阶段性总结

  • 大问句是出现问题的导火索,其他同情况的JAVA应用没问题只是没达到9111量级

  • 经考证jdk_131之前的版本,使用的是宿主机CPU资源,像datacache已确认

  • Java程序拿到是CPU核心数在没有CPU密集情况下一般情况也不会出现问题,将会增加宿主机计算资源

  • 容器相比于虚拟机完全虚拟出一台机器,容器只是在物理机上层写资源隔离调度的代码,这是它的优势,也是它的风险.像所分配的核心数其实不是论几个的,它的单位是像4核配置里边是400000很精确的,体现出调度资源的分配

  • 9111问题转好,主要体现在CPU使用上:G1的使用,VM参数中线程的控制,容器对CPU的调度控制