性能测试能力提升-JVM GC监控和优化

一、背景

接着上一篇的知识:性能测试能力提升-JVM GC原理,本篇文章,我们将主要介绍JVM GC监控和优化相关的知识:

  • 命令行方式监控GC
  • 图形化方式监控GC
  • 什么时候需要开始GC优化?
  • GC优化的目的
  • GC优化的步骤
  • 常用JVM参数配置实例

二、JVM GC监控

2.1 命令行方式监控GC

  1. Linux下使用命令:which java, 找到JDK目录;
  2. 在JDK的bin目录下,使用命令:jps 查看JVM进程PID。 或者也可以使用: ps -ef | grep java 查看Java进程PID,信息也更多一些;
  3. 使用命令: jstat -gc 18004 1000 即可监控GC情况。其中: 18004是JAVA进程的端口号, 1000表示1000毫秒,也就是每隔一秒展示GC监控数据;

在这里插入图片描述
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:Eden区的大小
EU:Eden区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC: 压缩类空间大小
CCSU: 压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

2.2 图形化方式监控GC

  1. xshell 登录远程服务器,输入命令:which java, 找到Java的目录在哪里。
  2. 到Java目录下的/jre/lib/security下,修改 java.policy这个文件的内容:vi java.policy,
    在文件末位的 }; 前添加 permission java.security.AllPermission。
  3. 到Java目录的bin目录下,比如:/usr/java/jdk1.8.0_60/bin, 执行下面的命令,开启jstatd:
    ./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=xx.xx.xx.xx &
    xx.xx.xx.xx是你远程服务器的IP。
  4. 本地java安装目录下: C:\Program Files\Java\jdk1.7.0_80\bin 下,运行jvisualvm.exe, 添加远程主机,VisualVM会自动检测到jstatd连接并添加节点。
    在这里插入图片描述

三、JVM GC优化

3.1 什么时候需要开始GC优化?

1、如果你没有设定过JVM参数,使用的是默认参数,而系统充斥着大量的超时日志时,你就需要在你的系统中进行GC优化了;

2、在检查GC状态的过程中,你应该分析监控结果以便决定是否进行GC优化,如果分析结果表明执行GC的时间只有0.1-0.3秒,那你就没必要浪费时间去进行GC优化。但是,如果GC的执行时间是1-3秒,或者超过10秒,GC将势在必行;

3、但是,你需要时刻铭记一条:GC优化永远是最后一项任务。当出现性能问题时,如果你已经设置过JVM参数,那么GC优化永远不应该是第一优先选项,先排除服务器、数据库、程序代码常见性能问题后,再着手监控优化GC也不迟。
在这里插入图片描述

3.2 GC优化的目的

GC优化的主要目的有两个:
1、将转移到老年代的对象数量降低到最小;
2、减少full GC的执行时间;

为了达到上面的目的,一般地,你需要做的事情有:
1、减少使用全局变量和大对象(应用代码层面);
2、调整新生代的大小到最合适(JVM参数);
3、设置老年代的大小为最合适(JVM参数) ;
4、选择合适的GC收集器(JVM参数) ;

在这里插入图片描述

3.3 GC优化的步骤

1、监控GC状态:
首先你需要监控GC来检查在系统执行过程中GC的各种状态;

2、分析监控结果,决定是否进行GC优化:
分析监控结果,判断是优化应用程序代码 OR 优化JVM参数 OR 代码&参数都优化。代码优化就交给开发大哥自己玩儿去吧。参数优化看下面几条。

3、JVM参数优化:
主要为两方面:堆大小设置 和 GC收集器设置。

4、分析结果:
在调整了GC参数并持续收集24小时之后,开始对调整后结果进行分析。通过不断的调整GC收集器设置和堆大小设置找到最佳的参数配置。

5、如何最快的完成GC优化:
对比性能测试的结果应该是最快地方法,为每一台服务器设置不同的参数并监控他们的状态,强烈建议至少监控1或2天的数据。

6、网上别人的参数优化配置是否我可以照搬使用:
可以借鉴,但适合别人的服务器配置,不一定适合你的服务器配置,尤其是参数后的 value(值)是需要根据你自己的实际情况来设置的。

在这里插入图片描述

3.4 常用JVM参数配置实例

设置方式:
LINUX下查看Tomcat的目录:sudo find / -name tomcat, 然后到bin目录下,打开catalina.sh, 设置JAVA_OPTS=设置JVM参数;

之前某web项目的JVM优化后的参数配置如下:
JAVA_OPTS=“
-Xms512m
-Xmx6G
-Xmn3G
-XX:SurvivorRatio=4
-XX:MaxTenuringThreshold=3
-XX:ParallelGCThreads=12
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+CMSPermGenSweepingEnabled
-XX:CMSInitiatingPermOccupancyFraction=85
-XX:+DisableExplicitGC
-XX:CMSFullGCsBeforeCompaction=3
-XX:+UseCMSCompactAtFullCollection
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+CMSParallelRemarkEnabled
-XX:+CMSIncrementalMode”

各参数解释

堆大小设置
-Xmx6G:设置JVM最大可用内存为6G;
-Xms512m:设置JVM初始内存为512m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存;
-Xmn3G:设置年轻代大小为3G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8;
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6;
-XX:MaxTenuringThreshold=3:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

GC收集器设置:
-XX:ParallelGCThreads=12:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等;
-XX:+UseParNewGC: 设置年轻代使用ParNew收集器 。可与CMS收集同时使用;
-XX:+UseConcMarkSweepGC:设置年老代使用CMS收集器;
-XX:CMSInitiatingOccupancyFraction=75:老年代使用75%后开始CMS收集;
-XX:+CMSPermGenSweepingEnabled:允许对持久代进行GC;
-XX:CMSInitiatingPermOccupancyFraction=85:持久代使用85%后触发GC;
-XX:+DisableExplicitGC:禁用“System.gc()”, 避免程序代码手动触发FULL GC;
-XX:CMSFullGCsBeforeCompaction=3:由于CMS收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection:在FULL GC的时候,对老年代的内存空间进行压缩。可能会影响性能,但是可以消除碎片 ;
-XX:+UseCMSInitiatingOccupancyOnly:使用手动定义初始化定义开始CMS收集,禁止自行触发CMS GC;
-XX:+CMSParallelRemarkEnabled: 降低标记停顿,减少标记耗时;
-XX:+CMSIncrementalMode:使用增量模式,在增量模式下,CMS 收集器在并发阶段,不会独占整个周期,而会周期性的暂停,唤醒应用线程,把cpu资源让给正在运行的应用
。收集器把并发阶段工作,划分为片段,安排在次级(minor) 回收之间运行。这对需要低延迟,运行在少量CPU服务器上的应用很有用。

其他常用参数设置:
-XX:NewRatio=4: 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。如果设置了-Xmn, 此设置无效;
-Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右;
-XX:MaxPermSize=16m: 设置持久代大小为16m,持久代一般默认大小为64m ;

这样配置后,基本上能达到:
系统响应时间增快;
JVM回收速度增快同时又不影响系统的响应率;
JVM内存最大化利用;
线程阻塞情况最小化;

============================================================================

以上就是本次的全部内容,下一篇文章,我们将主要介绍以下方面的知识:

  • 什么时候开始考虑做全链路压测
  • 全链路压测前梳理
  • 全链路压测方法

如果对你有帮助,欢迎关注我的微信公众号:程序员杨叔,各类文章都会第一时间在上面发布,持续分享全栈测试知识干货,你的支持就是作者更新最大的动力~
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值