今天介绍下性能测试调优分析经典问题:内存泄漏代码级定位。
一、背景介绍
1、测试现象
对系统进行稳定性测试过程中,发现系统跑到5个小时左右时,开始出现周期性卡顿,每次卡顿15s左右,并且频率越来越高。
2、分析过程
通过卡顿的频率越来越高,并且是5小时后发生的,很容易联想到是内存泄漏问题,通过堆dump导出分析,定位到是java.util.concurrent.LinkedBlockingQueue类导致,提交开发更改业务逻辑后问题解决。
二、问题复现演示
该问题较典型,80%以上的内存泄漏问题通过此方法均可以快速定位。
1、业务简介
LinkedBlockingQueue
类是以链表结构实现高效线程安全队列,具有出色的并发性能、灵活的阻塞与非阻塞操作,以及适用于生产者和消费者模式的能力。
本次测试demo使用精简的LinkedBlockingQueue业务逻辑代替生产的复杂业务,说明问题即可。
通过图中业务可知,生产数据的速度要快于消费的速度造成内存泄漏,时间长了之后会引发内存溢出导致程序无响应。
2、测试代码准备
代码仓库地址:https://gitee.com/lhc0001/perf.git
生产者:com.example.perf.service.Memory.Producer
消费者:com.example.perf.service.Memory.Consumer
通过com.example.perf.controller.Memory接口触发生产、消费行为。
3、内存泄漏现象与定位
通过swaggerui触发内存泄漏接口,2分钟左右,系统报错Java heap space:
通过jconsole监控内存变化:老年代内存迅速增长到总内存的三分之二,340MB左右,持续不变。
jvisualVM进行内存dump与分析:
通过jvisualVM的堆Dump分析,可发现是LinkedBlockingQueue
队列上的消息占据了整个堆的96.1%的空间导致。
三、总结
通过本次测试代码与测试工具jconsole、jvisualVM简单分析,即可轻松定位系统的内存泄漏点,便于开发解决问题。测试同学们如果遇到类似的卡顿的频率越来越高,并且是X(X》=1)小时后发生的系统性能问题,可以通过上述方式快速定位。