• 【JVM】落日黄昏后:CMS垃圾回收器


    CMS(Concurrent Mark Sweep)应用场景

    CMS是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网网站或者基于浏览器的B/S系统的服务端上,这类应用通常都会较为关注服务的响应速度,希望系统停顿时间尽可能短,以给用户带来良好的交互体验。CMS收集器就非常符合这类应用的需求。

    CMS的运作过程

    图片
    CMS收集器是基于标记-清除算法实现的,整个过程分为四个步骤,包括:

    • 初始标记(initial mark)
      这个阶段是STW的,但仅仅只是标记一下GCRoots能直接关联到的对象,所以速度很快

    • 并发标记(concurrent mark)
      并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行

    • 重新标记(remark)
      这个阶段是STW的,为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短

    • 并发清除(concurrent sweep)
      清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的

    CMS的优点

    1. 并发收集垃圾
    2. 低延时

    CMS的缺点

    1. CMS对处理器资源非常敏感。并发标记阶段吞吐量较低,虽然不会导致用户线程停顿,但是会导致应用程序变慢。因为有一部分CPU资源被分配给了垃圾收集线程4核CPU会分配25%的资源给垃圾回收线程,核数越多,分配给垃圾回收线程的资源比例占总核数比例会下降。但是当CPU不足4核的时候,本来应用负载就已经很高了,如果再分一半的资源给垃圾收集线程就会导致程序的执行速度大幅度降低

    2. Con-current ModeFailure 触发Full GC(STW)交由Serial Old收集器来收集。由于在垃圾收集阶段用户线程还需要持续运行,那就还需要预留足够内存空间提供给用户线程使用,因此CMS收集器不能像其他收集器那样等待到老年代几乎完全被填满了再进行收集,必须预留一部分空间供并发收集时的程序运作使用。在JDK5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,如果在实际应用中老年代增长并不是太快,可以适当调高参数-XX:CMSInitiatingOccu-pancyFraction的值来提高CMS的触发百分比,降低内存回收频率,获取更好的性能。但如果这个值给的过高,比如90%,这又会更容易面临另一种风险:要是CMS运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集,但这样停顿时间就很长了。所以这个参数设置得太高将会很容易导致大量的并发失败产生,性能反而降低,用户应在生产环境中根据实际应用情况来权衡设置

    3. 会产生内存空间碎片,分配大对象时空间不足提前触发FGC。CMS是一款基于“标记-清除”算法实现的收集器,收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很多剩余空间,但就是无法找到足够大的连续空间来分配当前对象,而不得不提前触发一次Full GC。不过也可以通过设置参数尽量的避免这个情况的发生,CMS收集器提供了一个-XX:+UseCMS-CompactAtFullCollection开关参数(默认是开启的,此参数从JDK 9开始废弃),用于在CMS收集器不得不进行Full GC时开启内存碎片的合并整理过程,由于这个内存整理必须移动存活对象,(在Shenandoah和ZGC出现前)是无法并发的。这样空间碎片问题是解决了,但停顿时间又会变长,因此虚拟机设计者们还提供了另外一个参数-XX:CMSFullGCsBeforeCompaction(此参数从JDK 9开始废弃),这个参数的作用是要求CMS收集器在执行过若干次(数量由参数值决定)不整理空间的Full GC之后,下一次进入Full GC前会先进行碎片整理(默认值为0,表示每次进入Full GC时都进行碎片整理)

    CMS特别需要注意的参数

    • -XX:CMSInitiatingOccu-pancyFraction:设置触发老年代回收的阈值,避免发生Concurrent Mode Failure引发FGC
    • -XX:+UseCMS-CompactAtFullCollection:在CMS收集器不得不进行Full GC时开启内存碎片的合并整理过程
    • -XX:CMSFullGCsBeforeCompaction

    关于CMS的总结

    虽然开创了并发回收垃圾的先河但由于有Con-current ModeFailure会触发FGC这个致命性的缺点,因此没有任何版本的JDK采用CMS作为默认的垃圾回收器,JDK9中CMS已经消失,但CMS并发回收垃圾的思想却一直在延续

  • 相关阅读:
    js,JavaScript,a标签onclick传递参数不对,A标签调用js函数写法总结
    Java两大测试方法Junit和TestNG的比较
    java简单的测试方法执行了多少时间
    利用Chrome的Performance工具排查页面性能问题(原叫timeline)
    P3317 [SDOI2014]重建(Matrix-tree+期望)
    P2221 [HAOI2012]高速公路(线段树)
    P2473 [SCOI2008]奖励关(期望)
    P3302 [SDOI2013]森林(主席树+启发式合并)
    bzoj3932 / P3168 [CQOI2015]任务查询系统(主席树+差分)
    P2219 [HAOI2007]修筑绿化带(单调队列)
  • 原文地址:https://www.cnblogs.com/zhangyibing/p/13793212.html
Copyright © 2020-2023  润新知