jmeter压力测试后的性能瓶颈分析及优化方法

1. 短时间的性能测试(5分钟)
性能测试结果显示正常
2. 中期2小时的性能测试
虽然有波动,总体还算正常 。
3. 中期4小时的性能测试
可以明显的看出性能明显下降 。
4. 查看内存及垃圾回收(jstat)
# jstat -gcutil -t43917 3000TimestampS0S1EOMCCSYGCYGCTFGCFGCTGCT27956.40.000.0018.8099.9795.1892.9122526435.2351350 4001.013 4436.24827959.50.000.0041.0599.9795.1892.9122526435.2351350 4001.013 4436.24827962.50.000.0068.2399.9795.1892.9122526435.2351350 4001.013 4436.24827965.40.000.0096.3599.9795.1892.9122526435.2351350 4001.013 4436.24827968.50.000.0010.7099.9895.1892.9122526435.2351351 4003.350 4438.58427971.50.000.0028.3499.9895.1892.9122526435.2351351 4003.350 4438.58427974.50.000.0047.0199.9895.1892.9122526435.2351351 4003.350 4438.58427977.50.000.0064.5999.9895.1892.9122526435.2351351 4003.350 4438.58427980.50.000.0083.3999.9895.1892.9122526435.2351351 4003.350 4438.58427983.50.000.00 100.0099.9895.1892.9122526435.2351352 4003.350 4438.58427986.50.000.0012.6999.9895.1892.9122526435.2351352 4005.704 4440.93827989.50.000.0029.4899.9895.1892.9122526435.2351352 4005.704 4440.93827992.50.000.0045.2499.9895.1892.9122526435.2351352 4005.704 4440.93827995.50.000.0059.9799.9895.1892.9122526435.2351352 4005.704 4440.93827998.50.000.0074.4599.9895.1892.9122526435.2351352 4005.704 4440.93828001.50.000.0086.4099.9895.1892.9122526435.2351352 4005.704 4440.93828004.50.000.00 100.0099.9895.1892.9122526435.2351353 4005.704 4440.93828007.50.000.00 100.0099.9895.1892.9122526435.2351353 4005.704 4440.93828010.50.000.0024.6399.9795.1892.9122526435.2351353 4010.111 4445.34628013.50.000.0049.5599.9795.1892.9122526435.2351353 4010.111 4445.34628016.50.000.0086.7499.9795.1892.9122526435.2351353 4010.111 4445.34628019.50.000.00 100.0099.9795.1892.9122526435.2351354 4010.111 4445.346
可以看出全局垃圾回收非常频繁 。
5. 查看内存直方图(jmap)
性能下降时的查询结果:
# jmap -histo 43917 | morenum#instances#bytesclass name----------------------------------------------1:4885725816256552[C2:4884972117239328java.lang.String3:53200263840240com.xxx.xxxx.dao.model.AcsBusinessLogService4:55480648822928java.lang.reflect.Method5:53200225536096org.springframework.aop.framework.ReflectiveMethodInvocation6:53200217024064java.util.concurrent.FutureTask7:57047114718728[Ljava.lang.Object;8:1586612960848[B9:53205412769296java.util.Date10:53200412768096java.util.concurrent.LinkedBlockingQueue$Node11:53200212768048org.springframework.aop.interceptor.AsyncExecutionInterceptor$$Lambda$1601/68449831812:717432295776java.util.concurrent.ConcurrentHashMap$Node13:186642086616java.lang.Class14:130471659328[I15:319889088[Ljava.util.concurrent.ConcurrentHashMap$Node;
可以看出字符数组类型数据[C,实例数488万个,占用空间816MB,e类型数据53万个,占用空间63MB,这些数据说明有空间没有及时释放 。
字符串类型数据,实例数488万个,占用空间117MB 。
出现上述情况的可能原因有两个:一个是在性能测试的时候,新生成的实例的速度远大于回收的速度,导致实例数的不断增加 。第二个原因就是程序中存在内存泄漏,有部分实例生成后无法释放 。
6. 性能测试几小时后查看内存直方图(jmap)

jmeter压力测试后的性能瓶颈分析及优化方法

文章插图
# jmap -histo 43917 | morenum#instances#bytesclass name----------------------------------------------1:9464611657136[C2:1051011349640[B3:122414028096[I4:717462295872java.util.concurrent.ConcurrentHashMap$Node5:940292256696java.lang.String6:186642086616java.lang.Class7:228042006752java.lang.reflect.Method8:380341924432[Ljava.lang.Object;9:319889088[Ljava.util.concurrent.ConcurrentHashMap$Node;10:19625785000java.util.LinkedHashMap$Entry11:46489743824java.lang.Object12:27776666624java.util.ArrayList13:5944602456[Ljava.util.HashMap$Node;14:17998575936java.util.HashMap$Node15:12831513240org.antlr.v4.runtime.atn.BasicState
从这里可以看出,对比之前的数据,字符数组类型数据实例数只有9万,相比之前的488万大幅减少,占用空间11M,相比之前816M也是大幅减少 。
字符串数据9万个,相比之前的488万,大幅减少,占用空间2MB,幅度也大幅减少 。
e实例对象没有了,说明被回收了 。
通过这些数据可以说明,之前的数据增多原因是内存回收速度跟不上的,而不是内存无法释放造成的 。
7. 相对简单的应对方法
对分配的内存空间在使用结束后,及时设置为空,方便垃圾回收能够及时回收 。
8. 相对复杂更有效的应对方法
根据程序频繁申请和释放内存的特点,采用内存池技术,预先建立一个内存池,需要内存的时候,从内存池中申请,使用完毕释放到内存池,当发现内存池大小不足时,扩充内存池的大小 。这种方法就是把内存的申请和释放,在程序中处理了,而不是依赖jvm虚拟机来处理 。
【jmeter压力测试后的性能瓶颈分析及优化方法】这种方法,也提高了程序的复杂性,需要对内存池技术比较熟悉,有比较丰富的经验才行 。