深刻探究jvm之GC的参数调优

  在上一篇博客记录了GC的算法及种类,这篇博客主要记录一下GC的参数如何调整以提升jvm的性能。算法

1、堆的回顾:多线程

  

 

                         

  堆的内存空间整体分为新生代和老年代,老年代存放的老年对象,新构造的对象分配在eden区中(栈上分配及新生代内存不足的状况除外)。在通过GC以后,幸存下来的对象会被分配到幸存代中,s0与s1是两块彻底相同的内存区域,采用复制算法,在迭代后交换内存空间。通过若干次GC后,仍然未被回收的对象会被分配到老年代中。并发

2、GC参数--串行收集器(Serial)jvm

   串行收集器有如下几个特色:工具

  1)最古老、最稳定性能

  2)效率高测试

  3)可能产生较长时间的停顿,只是用一个线程进行回收,没法发挥多核CPU的优点。(全局停顿在上一篇有介绍过)网站

  经过-XX:+UseSerialGC参数启用,启用以后,新生代和老年代会使用串行回收,新生代会采用复制算法,老年代会使用标记-压缩算法。(参见上一篇博客)spa

  串行回收器的示意图以下:线程

  参数分别记录了新生代和老年代的回收状况。

3、GC参数--并行收集器(PerNew)

  PerNew有如下几个特色:

  1)是Serial收集器新生代的并行版本

  2)采用的是复制算法

  3) 是多线程运行的,须要多核CPU的支持。

  经过-XX:+UsePerNewGC参数启用,启用以后,新生代采用并行回收,而老年代仍然使用串行回收,采用复制算法。能够经过-XX:ParallelGCThreads参数来限制线程的数量;

  经过-XX:MaxGCPauseMills参数控制最大停顿时间,单位是毫秒;GC会尽力保证回收时间不超过设定值;

  经过-XX:GCTimeRatio参数控制收集时间占总时间的比,取值范围是0-100;默认是1,即最大容许1%时间用来作GC。

  上述两个参数是矛盾的,由于停顿时间和吞吐量不可能同时调优的。GC的次数减小,必然致使单次停顿的时间变长,反之亦然;所以在权衡参数时要抓住性能瓶颈。

  并行回收器的示意图以下:

  须要注意的一点是,并行收集器只在多核CPU的状况下能提高性能,同时要控制好线程数,不然效率反而打折扣。

4、Paraller收集器

  Paraller收集器的特色以下:

  1)相似于ParNew收集器

  2)新生代采用复制算法,老年代使用标记-压缩算法。

  3)更加关注于吞吐量

  -XX:UseParallerGC参数:使用Paraller收集器,新生代采用并行收集,老年代采用串行收集;

  -XX:UseParallerOldGC参数:使用Paraller收集器,新生代和老年代都采用并行收集。

  Paraller收集器示例图:

 5、CMS收集器(Concurrent Mask Sweep)

  主要的特色以下:

  1)采用的是标记-清除算法

  2)与标记-压缩算法相比,在并发阶段(与应用程序线程同时执行)会下降吞吐量。

  3)老年代的收集器,并不影响新生代收集器,新生代仍然采用ParNew收集器。

  经过-XX:UseConcMarkSweepGC参数启用。

  CMS运行过程比较复杂,着重实现了标记的过程,可分为:

  ①初始标记:根对象能够直接关联到对象(速度很快);

  ②并发标记:同应用程序线程同时进行,标记全部的对象;

  ③从新标记:因为并发标记时,应用程序线程仍然在运行,所以在正式清理前,须要再次作修正;

  ④并发清除:基于以上的标记结果,直接清理对象。

  注意,在并发标记阶段,一样会产生全局停顿现象,只不过是尽量的减小了全局停顿的时间,在应用程序运行过程当中,会一直产生垃圾,没法进行标记。

  CMS收集器示例图以下:

  因为在一些标记过程当中与应用程序并行,以保证可用对象的地址不发生改变,因此只能简化标记算法而采用标记-清除算法。另外,CMS收集器会影响系统总体的吞吐量,如在用户线程运行的过程当中,会占用CPU进行GC操做;同时还存在清理不完全的状况,在一些标记的过程当中,用户的应用程序仍然会产生新的垃圾不会被标记。

  注意,由于和用户的应用程序并发,不能在空间快满时才进行清理操做,经过-XX:CMSInitiatingOccupancyFraction参数设置触发GC的阈值,若是内存预留的空间不足,就会引发concurrent mode failure。发生错误的后备方法是,经过串行收集器进行收集,但会产生比较长时间的停顿。

  标记-清除算法会产生碎片空间,所以咱们须要进行碎片整理:

  经过-XX:UseCMSCompactAtFullCollection参数使在进行FullGC以后进行一次整理,这个整理过程是独占的,会引发停顿时间变长;

  经过-XX:CMSFullGCsBeforeCompaction参数设置进行几回FullGC以后进行一次碎片整理;

  经过-XX:ParallelCMSThreads设定CMS的线程数量。

6、GC参数整理:

  -XX:+UseSerialGC:在新生代和老年代使用串行收集器;

  -XX:SurvivorRatio:设置eden区大小和survivor区大小的比例;

  -XX:NewRatio:设置新生代和老年代的大小比例;

  -XX:+UseParNewGC:在新生代使用并行收集器;

  -XX:+UseParellelGC:新生代使用并行回收收集器;

  -XX:+UseParallelOldGC:老年代使用并行回收收集器;

  -XX:ParallelGCThreads:设置用于垃圾回收的线程数;

  -XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器;

  -XX:ParallelCMSThreads:设定CMS的线程数量;

  -XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后被触发;

  -XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存的碎片整理;

  -XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收以后进行一次内存压缩;

  -XX:+CMSClassUnloadingEnabled:容许对类元数据进行回收;

  -XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启用CMS回收;

  -XX:UseCMSInitiatingOccupancyOnly:只有到达阈值的时候才进行CMS回收。

 7、GC参数实例:

  环境:Tomcat七、JSP网站、JDK六、测试网站的吞吐量及延时。

  工具:Jmeter,创建10个线程,每一个线程请求Tomcat 1000次 共1w次。

  目的:让Tomcat有一个不错的吞吐量。

  结构:Tomcat与Jmeter分开部署,防止Jmeter对Tomcat的性能产生影响。

    

 一、参数:set CATALINA_OPTS=-server -Xloggc:gc.log -XX:+PrintGCDetails -Xms32M -Xmx32M -XX:+HeapDumpOnOutOfMemeryError -XX:+UseSerialGC -XX:PermSize=32M

  

二、参数:set CATALINA_OPTS=-Xmx512M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails

  将最大堆内存改成512m,结果FullGC发生不多,基本上都是MinorGC。吞吐量由540提升到了650,同时堆大小也在自动拓展,由开始的15872K拓展到38秒的60456K。

三、参数:set CATALINA_OPTS=-Xmx512M -Xms=64M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails

  将堆内存的初始大小设置为64M,GC数量减小,大部分都是MinorGC.吞吐量由651提高到了674。

四、参数:set CATALINA_OPTS=-Xmx512M -Xms=64M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails -XX:+UseParallelGC -XX:+UseParallelOldGC

   -XX:ParallelGCThreads

  新生代和老年代都使用并行回收收集器,GC本来压力不大,因此影响很小。

五、参数:set CATALINA_OPTS=-Xmx40M -Xms40M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails

  减小堆大小,增长GC压力,默认使用串行回收收集器,吞吐量为646。

六、参数:set CATALINA_OPTS=-Xmx40M -Xms40M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails -XX:+UseParallelOldGC -XX:ParallelGCThreads

   减小堆大小,增长GC压力,老年代使用并行回收收集器,吞吐量由646提升到了685。

七、参数:set CATALINA_OPTS=-Xmx40M -Xms40M -XX:MaxPermSize=32M -Xloggc:gc.log -XX:PrintGCDetails -XX:+UseParNewGC

   减小堆大小,增长GC压力,新生代使用并行回收收集器,吞吐量由685降低到了660。可见老年代的GC回收机制对系统性能影响更大一些。

八、不添加任何参数,使用JDK6与JDK7对比

  发现JDK版本对于系统性能影响不容忽视。升级JDK版本可能会带来额外的性能提高!

相关文章
相关标签/搜索