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

一、堆的回顾:

  

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

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

   串行收集器有以下几个特点:

  1)最古老、最稳定

  2)效率高

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

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

  串行回收器的示意图如下:

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

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

  PerNew有以下几个特点:

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

  2)采用的是复制算法

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

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

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

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

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

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

  需要注意的一点是,并行收集器只在多核CPU的情况下能提升性能,同时要控制好线程数,否则效率反而打折扣。

四、Paraller收集器

  Paraller收集器的特点如下:

  1)类似于ParNew收集器

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

  3)更加关注于吞吐量

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

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

  Paraller收集器示例图:

五、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的线程数量。

六、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回收。

七、GC参数实例:

  环境:Tomcat7、JSP网站、JDK6、测试网站的吞吐量及延时。

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

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

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

    

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

  

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

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

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

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

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

   -XX:ParallelGCThreads

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

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

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

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

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

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

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

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

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

深入探究jvm之GC的参数调优的更多相关文章

  1. JVM内存结构、参数调优和内存泄露分析

    1. JVM内存区域和参数配置 1.1 JVM内存结构 Java堆(Heap) Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都 ...

  2. JVM内存模型及参数调优

    堆.栈.方法区概念区别 1.堆 堆内存用于存放由new创建的对象和数组.在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.根据垃圾回收机制的不同, Java堆有可能拥有不同的结构,最为常见的就是 ...

  3. JVM性能参数调优实践,不会执行Full GC,网站无停滞

    原文来自:http://bbs.csdn.net/topics/310110257 本文只做整理记录,供个人学习. 1 JVM参数调优是个很头痛的问题,设置的不好,JVM不断执行Full GC,导致整 ...

  4. jvm系列(六):Java服务GC参数调优案例

    本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...

  5. JVM参数调优

    JVM参数调优 JVM参数调优是一个很头痛的问题,可能和应用有关系,下面是本人一些调优的实践经验,希望对读者能有帮助,环境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G内存,d ...

  6. (转)JVM参数调优八大技巧

    这里和大家分享一下JVM参数调优的八条经验,JVM参数调优,这是很头痛的问题,设置的不好,JVM不断执行FullGC,导致整个系统变得很慢,网站停滞时间能达10秒以上,相信通过本文的学习你对JVM参数 ...

  7. 性能测试三十六:内存溢出和JVM常见参数及JVM参数调优

    堆内存溢出: 此种溢出,加内存只能缓解问题,不能根除问题,需优化代码堆内存中存在大量对象,这些对象都有被引用,当所有对象占用空间达到堆内存的最大值,就会出现内存溢出OutOfMemory:Java h ...

  8. JVM 堆参数调优 (四)

    堆参数调优 1.堆的结构 JAVA7 堆逻辑上分为:新生区.养老区.永久区:实际上堆只有新生区.养老区: Minor GC:轻量的垃圾回收:   Major GC(Full GC):重量级垃圾回收. ...

  9. JVM参数调优:Eclipse启动实践

    本文主要参考自<深入理解 Java 虚拟机>.这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过程,包括了 JVM(Java ...

随机推荐

  1. 每次都要重新编译?太慢!让跨平台的 MSBuild/dotnet build 的 Target 支持差量编译

    如果你干预到了项目的编译过程,可能就需要考虑到差量编译了.不然--当你的项目大起来的时候,就会感受到每次都重新编译时,每次重复调试的过程都要进行漫长等待时的绝望和无奈. 如果你正遭遇差量编译失效,每次 ...

  2. 前端(六):JavaScript面向对象之宿主对象

    宿主对象即浏览器提供的对象,主要包括DOM对象和BOM对象. 一.DOM源起 1.SGML.XML和XHTML SGML(标准通用标记语言)是定义使用标签来表示数据的标记语言的语法. - 标签由一个小 ...

  3. 《selenium2 python 自动化测试实战》(3)——操作测试对象

    上一节我们说了如何定位元素,定位到元素以后就涉及到对元素的操作了,webdriver中常用的操作元素的方法有: clear  ——用于清除输入框的默认内容 send_keys  ——用于在一个输入框里 ...

  4. ballerina 学习六 xml && json

    ballerina xml && json 参考使用 代码比较简单,使用起来还是比较方便的 xml 代码说明: import ballerina/io; function main ( ...

  5. 下ue节点

    #!/bin/bash action=$1 port=$2 file="/home/operation/workspace/renderingengine/engine/services.t ...

  6. jdk1.8新特性之方法引用

    方法引用其实就是方法调用,符号是两个冒号::来表示,左边是对象或类,右边是方法.它其实就是lambda表达式的进一步简化.如果不使用lambda表达式,那么也就没必要用方法引用了.啥是lambda,参 ...

  7. couchdb的使用例子

    couchdb安装 sudo apt-get install erlang sudo apt-get install libmozjs185-dev libicu-dev 下载源码,编译安装 启动以后 ...

  8. TransportClient操作详解

    Elasticsearch JAVA操作有三种客户端: 1.TransportClient 2.JestClient 3.RestClient 还有种是2.3中有的NodeClient,在5.5.1中 ...

  9. print 和 println的区别

    println 输出字符后,下一个输出的字符会换行展示 print 输出字符后,下一个输出字符不会会换展示

  10. Account银行账户

    package com.hanqi; //账户类 public class Account { String ZhangHao; double CunKuanYuE; Account(String Z ...