`

CMS gc实践总结(转载)

阅读更多

    首先感谢阿宝 同学的帮助,我才对这个gc算法的调整有了一定的认识,而不是停留在过去仅仅了解的阶段。在读过sun的文档和跟阿宝讨论之后,做个小小的总结,如果有谬误,敬请指正。
    CMS,全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性需求 大于对吞吐量的要求,能够承受垃圾回收线程和应用线程共享处理器资源,并且应用中存在比较多的长生命周期的对象的应用。CMS是用于对tenured generation的回收,也就是年老代的回收,目标是尽量减少应用的暂停时间,减少full gc发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代。在我们的应用中,因为有缓存的存在,并且对于响应时间也有比较高的要求,因此希 望能尝试使用CMS来替代默认的server型JVM使用的并行收集器,以便获得更短的垃圾回收的暂停时间,提高程序的响应性。
    CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:
    初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)
    其中的1,3两个步骤需要暂停所有的应用程序线程的。第一次暂停从root对象开始标记存活的对象,这个阶段称为初始标记;第二次暂停是在并发标记之后, 暂停所有应用程序线程,重新标记并发标记阶段遗漏的对象(在并发标记阶段结束后对象状态的更新导致)。第一次暂停会比较短,第二次暂停通常会比较长,并且 remark这个阶段可以并行标记。

    而并发标记、并发清除、并发重设阶段的所谓并发,是指一个或者多个垃圾回收线程和应用程序线程并发地运行 ,垃圾回收线程不会暂停应用程序的执行,如果你有多于一个处理器,那么并发收集线程将与应用线程在不同的处理器上运行,显然,这样的开销就是会降低应用的吞吐量。Remark阶段的并行 ,是指暂停了所有应用程序后,启动一定数目的垃圾回收进程进行并行标记,此时的应用线程是暂停的。

    CMS的young generation的回收采用的仍然是并行复制收集器,这个跟Paralle gc算法是一致的。

    下面是参数介绍和遇到的问题总结,

1、启用CMS:-XX:+UseConcMarkSweepGC 。 咳咳,这里犯过一个低级错误,竟然将+号写成了-号

 

2。CMS默认启动的回收线程数目是  (ParallelGCThreads + 3)/4) ,如果你需要明确设定,可以通过-XX: ParallelCMSThreads =20来设定,其中 ParallelGCThreads是年轻代的并行收集线程数


3、CMS是不会整理堆碎片的,因此为了防止堆碎片引起full gc,通过会开启CMS阶段进行合并碎片选项:-XX:+UseCMSCompactAtFullCollection ,开启这个选项一定程度上会影响性能,阿宝的blog里说也许可以通过配置适当的CMSFullGCsBeforeCompaction来调整性能,未实践。

4.为了减少第二次暂停的时间,开启并行remark: -XX:+CMSParallelRemarkEnabled 。如果remark还是过长的话,可以开启-XX:+CMSScavengeBeforeRemark 选项,强制remark之前开始一次minor gc,减少remark的暂停时间,但是在remark之后也将立即开始又一次minor gc。

5.为了避免Perm区满引起的full gc,建议开启CMS回收Perm区选项:

+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled


6.默认CMS是在tenured generation沾满68%的时候开始进行CMS收集,如果你的年老代增长不是那么快,并且希望降低CMS次数的话,可以适当调高此值:
-XX:CMSInitiatingOccupancyFraction=80

这里修改成80%沾满的时候才开始CMS回收。

7.年轻代的并行收集线程数默认是(cpu <= 8) ? cpu : 3 + ((cpu * 5) / 8),如果你希望降低这个线程数,可以通过-XX:ParallelGCThreads= N 来调整。

8.进入重点,在初步设置了一些参数后,例如:

 

Java代码  收藏代码
  1. -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=64m  
  2. -XX:MaxPermSize=64m -XX:-UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection  
  3. -XX:CMSInitiatingOccupancyFraction=80  -XX:+CMSParallelRemarkEnabled  
  4. -XX:SoftRefLRUPolicyMSPerMB=0   

 

需要在生产环境或者压测环境中测量这些参数下系统的表现,这时候需要打开GC日志查看具体的信息,因此加上参数:

-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:/home/test/logs/gc.log

在运行相当长一段时间内查看CMS的表现情况,CMS的日志输出类似这样:

 

Java代码  收藏代码
  1. 4391.322 : [GC [ 1  CMS-initial-mark: 655374K(1310720K)] 662197K(1546688K),  0.0303050  secs] [Times: user= 0.02  sys= 0.02 , real= 0.03  secs]  
  2. 4391.352 : [CMS-concurrent-mark-start]  
  3. 4391.779 : [CMS-concurrent-mark:  0.427 / 0.427  secs] [Times: user= 1.24  sys= 0.31 , real= 0.42  secs]  
  4. 4391.779 : [CMS-concurrent-preclean-start]  
  5. 4391.821 : [CMS-concurrent-preclean:  0.040 / 0.042  secs] [Times: user= 0.13  sys= 0.03 , real= 0.05  secs]  
  6. 4391.821 : [CMS-concurrent-abortable-preclean-start]  
  7. 4392.511 : [CMS-concurrent-abortable-preclean:  0.349 / 0.690  secs] [Times: user= 2.02  sys= 0.51 , real= 0.69  secs]  
  8. 4392.516 : [GC[YG occupancy:  111001  K ( 235968  K)] 4392.516 : [Rescan (parallel) ,  0.0309960  secs] 4392.547 : [weak refs processing,  0.0417710  secs] [ 1  CMS-remark: 655734K(1310720K)] 766736K(1546688K),  0.0932010  secs] [Times: user= 0.17  sys= 0.00 , real= 0.09  secs]  
  9. 4392.609 : [CMS-concurrent-sweep-start]  
  10. 4394.310 : [CMS-concurrent-sweep:  1.595 / 1.701  secs] [Times: user= 4.78  sys= 1.05 , real= 1.70  secs]  
  11. 4394.310 : [CMS-concurrent-reset-start]  
  12. 4394.364 : [CMS-concurrent-reset:  0.054 / 0.054  secs] [Times: user= 0.14  sys= 0.06 , real= 0.06  secs]  
 


其中可以看到CMS-initial-mark阶段暂停了0.0303050秒,而CMS-remark阶段暂停了0.0932010秒,因此两次暂停的总共时间是0.123506秒,也就是123毫秒左右。两次短暂停的时间之和在200以下可以称为正常现象。

但是你很可能遇到两种fail引起full gc :Prommotion failed和Concurrent mode failed。

Prommotion failed的日志输出大概是这样:

 

Java代码  收藏代码
  1. [ParNew (promotion failed): 320138K->320138K(353920K),  0.2365970  secs] 42576.951 : [CMS: 1139969K->1120688K(  
  2. 166784K), 9.2214860  secs] 1458785K->1120688K(2520704K),  9.4584090  secs]  


这个问题的产生是由于救助空间不够,从而向年老代转移对象,年老代没有足够的空间来容纳这些对象,导致一次full gc的产生。解决这个问题的办法有两种完全相反的倾向:增大救助空间、增大年老代或者去掉救助空间 。 增大救助空间就是调整-XX:SurvivorRatio参数,这个参数是Eden区和Survivor区的大小比值,默认是32,也就是说Eden区是 Survivor区的32倍大小,要注意Survivo是有两个区的,因此Surivivor其实占整个young genertation的1/34。调小这个参数将增大survivor区,让对象尽量在survitor区呆长一点,减少进入年老代的对象。去掉救助空 间的想法是让大部分不能马上回收的数据尽快进入年老代,加快年老代的回收频率,减少年老代暴涨的可能性,这个是通过将-XX:SurvivorRatio 设置成比较大的值(比如65536)来做到。在我们的应用中,将young generation设置成256M,这个值相对来说比较大了,而救助空间设置成默认大小(1/34),从压测情况来看,没有出现prommotion failed的现象,年轻代比较大,从GC日志来看,minor gc的时间也在5-20毫秒内,还可以接受,因此暂不调整。

Concurrent mode failed的产生是由于CMS回收年老代的速度太慢,导致年老代在CMS完成前就被沾满,引起full gc,避免这个现象的产生就是调小-XX:CMSInitiatingOccupancyFraction 参数的值,让CMS更早更频繁的触发,降低年老代被沾满的可能。我们的应用暂时负载比较低,在生产环境上年老代的增长非常缓慢,因此暂时设置此参数为80。在压测环境下,这个参数的表现还可以,没有出现过Concurrent mode failed。


参考资料:
JDK5.0垃圾收集优化之--Don't Pause 》 by 江南白衣
《记一次Java GC调整经历》1 ,2 by Arbow
Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
Tuning Garbage Collection with the 5.0 JavaTM Virtual Machine

分享到:
评论

相关推荐

    JAVA gc日志分析工具GChisto及CMS GC补丁

    GChisto及CMS GC相应补丁文件,补丁文件未亲测。 This patch adds the following features and improvements when using CMS GC in incremental mode: detecting Full GCs corrected parsing errors when using -XX:...

    cms总结文档

    cms总结文档,cms总结文档cms总结文档cms总结文档cms总结文档,cms总结文档

    毕业综合实践报告实例网站CMS开发实践.doc

    【毕业综合实践报告实例网站CMS开发实践】 毕业综合实践报告主要关注的是CMS(Content Management System,内容管理系统)的开发过程,这是一个用于构建和管理网站的软件平台,它允许非技术人员通过用户友好的界面...

    帝国cms个人博客(转载)

    【标题】"帝国cms个人博客(转载)"所涉及的知识点主要集中在网站开发领域,特别是使用帝国CMS系统来创建一个个人博客的过程。帝国CMS是一款基于PHP+MySQL开发的内容管理系统,它以其强大的功能、灵活的扩展性和易用...

    EdwardLee03#issue-case#万恶的swap(CMS GC的remark耗时好几秒)1

    【现象】悲催的是运行了几天后,突然有几台机器开始报警,上机器看到的现象是CMS GC的remark竟然花了20s+,而实际上这个时候old也就用了2g+,这个时

    cms源码 cms源码

    CMS,全称Content Management System,即内容管理系统,是一种用于创建和管理数字内容的软件平台。在IT领域,CMS源码通常指的是...理解并利用这些资源,无论是CMS源码还是Python程序,都需要一定的编程基础和实践经验。

    CMS32F033用户手册_V1.01(1)_CMS32M53XX_CMS32F033ss24_CMS32F033C程序_cms

    《CMS32F033用户手册》是针对CMS32系列微控制器的重要技术文档,主要涵盖CMS32F033型号的详细信息。该手册由V1.01版本更新,...通过深入学习和实践,开发者可以充分利用CMS32F033的潜力,打造高效、可靠的嵌入式系统。

    支持杰奇cms在Liunx下可视化采集数据带语音视频教程 支持船说cms.zip

    总结来说,这个压缩包提供的教程资源将帮助用户深入理解如何在Linux操作系统中使用杰奇CMS和船说CMS进行数据采集,同时通过可视化的界面和语音指导,使学习过程更加直观易懂。对于需要在Linux环境中管理和处理大量...

    苹果cms在线采集70多个接口.zip_苹果CMS多线路_苹果cms QQjs_苹果cms sitemap_苹果cms采集_苹

    苹果CMS是一款广泛应用于建站的开源内容管理系统,尤其在视频网站搭建方面表现出色。这个压缩包文件"苹果cms在线采集70多个接口.zip"显然包含了与苹果CMS相关的接口资源,这些接口可能用于从不同源自动抓取和更新...

    GCviewer-1.35 GC分析工具

    5. **GC策略**:支持不同的垃圾收集器策略,如Serial、Parallel、CMS、G1等。 ### 三、如何使用GCviewer 1. **下载与解压**:首先,你需要下载GCviewer的压缩包,例如gcviewer-1.35-dist-mac,解压后得到包含可...

    Java GC的过程

    总结,Java GC的过程涉及内存的自动管理,包括对象的可达性分析、垃圾收集器的选择、GC过程的执行以及调优策略。理解这些概念对于优化Java应用的性能至关重要。在实际开发中,我们需要根据应用的特性和需求来选择...

    gcviewer-1.37-SNAPSHOT.jar

    用于分析 java gc日志文件。根据日志中的CMS GC统计信息可得到Full GC(也可以理解为Major GC)以及Minor GC相关数据

    帝国CMS学生学习知识点总结作文试题练习题考试资讯网站源码 带手机版

    帝国CMS学生学习知识点总结作文试题练习题考试资讯网站源码 带手机版 帝国CMS《学习》模板,简洁大气访问快,带一个漂亮体验好的手机端,中小学生知识点总结、试题、练习题、考试资讯、作文大全,学习方法技巧等,百度...

    jvm 参数及gc详解

    - CMS(Concurrent Mark Sweep)GC:并行标记,低延迟,适用于响应时间敏感的应用。 - G1(Garbage-First)GC:新一代的垃圾收集器,目标是达到可预测的暂停时间。 4. GC调优 调优主要涉及选择合适的垃圾收集器...

    jvm性能调优-垃圾收集器parnew&CMS底层三色标记算-performance-gc-parnew-cms.zip

    然而,CMS在内存压力过大时,可能会出现“Concurrent Mode Failure”(并发模式失败)问题,此时GC需要暂停应用进行“预清理”,以避免在并发标记阶段因空间不足而被迫暂停应用。为了避免这种情况,可以通过调整`-XX...

    苹果CMS一键采集+播放器整合方法.zip_cms播放器_cms采集_magickog_苹果cms开发_苹果cms采集器

    总结,苹果CMS的一键采集和播放器整合是构建视频网站的重要环节,涉及到网络爬虫技术、播放器集成、图像处理和CMS系统开发等多个方面。掌握这些知识,不仅能提升网站运营的效率,也能提供更好的用户体验。对于想要...

    gcviewer.rar

    此外,它还可以帮助我们验证和调优JVM的垃圾收集器设置,如CMS、G1、ZGC或Shenandoah等。 在实际使用中,我们通常会配合JProfiler、VisualVM等其他性能分析工具,以获取更全面的系统视图。例如,JProfiler提供了更...

    visualGC.zip

    这些信息有助于我们分析GC策略的效果,比如是否需要调整新生代和老年代的比例,或者是否需要调整CMS、G1等不同的GC算法参数。 此外,VisualGC还能展示线程堆栈,帮助我们了解在GC发生时应用程序的运行状态,找出...

    帝国CMS中小学生学习模板学生知识点总结试题练习题考试资讯网站源码

    帝国CMS中小学生学习模板学生知识点总结试题练习题考试资讯网站源码 帝国CMS《学习》模板,简洁大气访问快,带一个漂亮体验好的手机端, 中小学生知识点总结、试题、练习题、考试资讯、作文大全,学习方法技巧等, 百度...

    gc回收机制

    Java垃圾收集(Garbage ...总结来说,GC回收机制是Java语言的一个重要特性,它自动管理内存,减少了内存泄漏的可能性。然而,理解和掌握GC的工作原理、不同类型的GC和如何优化GC,对于开发高性能的Java应用至关重要。

Global site tag (gtag.js) - Google Analytics