暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

程序员杨叔 2022-05-23
895

一、背景

接着上一篇的知识:性能测试能力提升-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这个文件的内容:

    vim 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内存最大化利用;
            线程阻塞情况最小化;



            END



            以上就是本次的全部内容,如果对你有帮助,麻烦点个赞+收藏+分享,你的支持就是作者更新最大的动力~

            下一篇文章,我们将主要介绍以下方面的知识:




            • 什么时候开始考虑做全链路压测

            • 全链路压测方法

            最后,欢迎加入杨叔的测试交流群,沟通交流日常测试工作相关内容,三个臭皮匠赛过诸葛亮,2022一起学习进步!



            往期精彩文章:




            性能测试能力提升-JVM GC原理

            性能测试能力提升-常用知识1

            你真的会写测试用例吗?

            springboot Demo框架实现注册登录

            性能调优必备:Arthas安装及常用命令教程




            文章转载自程序员杨叔,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论