`
pany
  • 浏览: 87991 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

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

- server  - Xms1536m  - Xmx1536m  - XX:NewSize = 256m  - XX:MaxNewSize = 256m  - XX:PermSize = 64m
- XX:MaxPermSize = 64m  - XX: - UseConcMarkSweepGC  - XX: + UseCMSCompactAtFullCollection
- XX:CMSInitiatingOccupancyFraction = 80   - XX: + CMSParallelRemarkEnabled
- XX:SoftRefLRUPolicyMSPerMB = 0


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

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

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

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]
4391.352 : [CMS - concurrent - mark - start]
4391.779 : [CMS - concurrent - mark:  0.427 / 0.427  secs] [Times: user = 1.24  sys = 0.31 , real = 0.42  secs]
4391.779 : [CMS - concurrent - preclean - start]
4391.821 : [CMS - concurrent - preclean:  0.040 / 0.042  secs] [Times: user = 0.13  sys = 0.03 , real = 0.05  secs]
4391.821 : [CMS - concurrent - abortable - preclean - start]
4392.511 : [CMS - concurrent - abortable - preclean:  0.349 / 0.690  secs] [Times: user = 2.02  sys = 0.51 , real = 0.69  secs]
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]
4392.609 : [CMS - concurrent - sweep - start]
4394.310 : [CMS - concurrent - sweep:  1.595 / 1.701  secs] [Times: user = 4.78  sys = 1.05 , real = 1.70  secs]
4394.310 : [CMS - concurrent - reset - start]
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的日志输出大概是这样:

 [ParNew (promotion failed): 320138K -> 320138K(353920K),  0.2365970  secs] 42576.951 : [CMS: 1139969K -> 1120688K(
2166784K), 
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。

分享到:
评论
1 楼 hairongtian 2012-09-01  
我想问一下在GC中的gc roots是什么?教科书的看不懂,能不能通俗的讲讲,最好给个实例解释一下,谢谢!

相关推荐

    resin-jvm 调优

    1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。 ...

    04-VIP-JVM垃圾收集器详解1

    1.垃圾收集器 1. -XX:+UseConcMarkSweepGC:启用cms 2. -XX:ConcGCThreads:并发的GC线程数 3. -XX:+U

    2019互联网面试题第2季.mmap

    尚硅谷周阳互联网大厂面试题(第2季) 脑图。包括JUC多线程并发、JVM和GC等目前大厂笔试中...下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践

    【原价2300!!】尚硅谷_互联网大厂高频重点面试题视频详细讲解

    JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、阻塞队列、...

    2019年互联网大厂高频重点面试题(第2季)

    本期内容包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、...

    2019互联网大厂高频重点面试题 (第2季)脑图-完结.txt

    本期内容包括JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。上半场,从多线程并发入手,分层递进讲解,逐步让大家掌握volatile、原子类和原子引用、CAS、ABA、Java锁机制、...

    高并发面试题-解答汇总

    针对高并发、JVM、GC大厂面试+详细解答总结汇总(对多线程、锁机制、内存分配、垃圾回收算法等,有这详细易懂的讲解!)

    JVM参数设置详细说明

    指定jvm的最小heap大小,如:-Xms=2g,高并发应用,建议和-Xmx一样,防止因为内存收缩/突然增大带来的性能影响。 c: -Xmn 指定jvm中New Generation的大小,如:-Xmn256m。这个参数很影响性能,如果你的程序需要比较...

    Java进阶教程解密JVM视频教程

    4. 了解 Java 内存模型相关知识,见识多线程并发读写共享数据时的问题和 Java 的解决方案。 适应人群 有一定的Java基础,希望提升 Java 内功的人群。 课程亮点 * 系统地学习 JVM 内存结构,垃圾回收、字节码与类...

    京东面试经历总结(近两年数据)

    1、JVM & GC 1)你们JVM线上使⽤的什么垃圾回收算法?CMS、G1 2)详细说㇐下CMS垃圾回收算法回收过程?4个阶段 3)CMS中的remark阶段⽐较慢,怎么分析和解决? - XX: +CMSScavengeBeforeRemark Remark前提前来㇐次...

    互联网大厂高频重点面试题1289477175.xmind

    3. JUC多线程及高并发+4. JVM + GC解析+6. NOSQL数据库Redis+相关源代码);我的这个看过尚硅谷面试第二季的估计都应该知道吧(github上的只有3. JUC多线程及高并发+4. JVM + GC解析,并且缺少),希望大家拿到之后,找到一...

    java数据分析源码-javaModel:java高级基础知识总结,算法,数据结构,多线程,jvm优化,spring源码分析,java新特性等

    一、多线程高并发(concurrent、jvm包) 1.JUC多线程及高并发 1.1 多线程集合 1.2 cas 1.3 锁 1.4 队列 1.5 线程池 2.JVM+GC解析 demo 二、JDK8新特性(lamp包) 1.四大函数式接口 2.方法引用 3.构造器引用 4.数组...

    尚硅谷_互联网大厂高频重点面试题(第2季).xmind

    下半场,逐步过渡到JVM和GC的知识,深度讲解多种常见OOM异常和JVM参数调优,以及串行并行并发G1等各种垃圾收集器的优化实践。 无论是进入职场不久的初级程序员,还是技术长期没有成长、正在吃老本走下坡路但还想涨...

    尚硅谷大厂高频面试题第二季视频资源.txt

    JUC多线程并发、JVM和GC等目前大厂笔试中会考、面试中会问、工作中会用的高频难点知识。 斩offer、拿高薪、跳槽神器,对标阿里P6的《尚硅谷_互联网大厂高频重点面试题(第2季)》发布。本套课程总结分析了2019年大厂...

    JAVA核心知识点整理

    java核心知识整理,jvm 线程 锁 集合 并发 数据库 网络

    java面试视频.part11.rar

    视频总共压缩了19包,需要全部下载完才能解压 适合java求职找工作的小伙伴 第1章 课程导学 ...Java多线程与并发 第9章 Java多线程与并发-原理 第10章 Java常用类库与技巧 第11章 Java框架-Spring 第12章 课程总结与展望

    java面试视频.part01.rar

    包含代码 视频总共压缩了19包,需要全部下载完才能解压 适合java求职找工作的小伙伴 ...第8章 Java多线程与并发 第9章 Java多线程与并发-原理 第10章 Java常用类库与技巧 第11章 Java框架-Spring 第12章 课程总结与展望

    java面试视频.part08.rar

    包含代码 视频总共压缩了19包,需要全部下载完才能解压 适合java求职找工作的小伙伴 ...第8章 Java多线程与并发 第9章 Java多线程与并发-原理 第10章 Java常用类库与技巧 第11章 Java框架-Spring 第12章 课程总结与展望

Global site tag (gtag.js) - Google Analytics