背景:
此系统功能上大抵分为两部分,一个是Web的管理平台,其二是定时检测、路由、转换发送报文的后端功能。系统主要计算在后端功能。管理平台的使用量很小,基本是配置及状态查看。
现象:
在测试数据中,处理5万单的文件。据相关开发人员描述,系统内存泄漏,系统运行越来越慢。
查看:
由开发人员提供的函数执行时间统计表来看,函数的平均执行时间并没有明显的降低。(此处开发人员将关注点放在了总时间)
经过使用工具查看,系统的内存使用持续增加,一直没有回落,两个小时内一直稳定在2G左右。
思路:
1、内存稳定2G不再增长,有可能是测试数据量的问题,也可能是内存使用基准就是2G,后续基本不再增长。
所以,最好再增长数据量做一次测试,以进一步确认。
2、假设内存泄漏,那么通过查看堆栈信息。由jvisualvm.exe查看实例数量统计,发现除了integer,char[]等基础类型数量非常大。而与系统有关的类的实例很少,或者处在循环中,有稳定的波动。
联想到可能有程序员定义全局的字段,导致一直累加增长。
通过关键字查找,未发现有此类现象。
再查看列表,除了基础数据类型多之外,HashMap及HashMap$Entry的实例也很多,达到百万个实例。通过查看工程代码,使用到Map的地方一般都在函数内的局部变量,不可能造成这么多的实例。
最后采用随机的方式,查看Map所关联的实例,发现都与HQLParser有对象相关。
由此联想到,可能是开发时,一些SQL或者HQL采用拼字符串的方式,且没有使用占位符。猜想Hibernate内部可能对这些SQL/HQL的语句进行一些缓存。导致HashMap的实例量剧增。
(最后通过测试,证实确实是此问题。错误的开发习惯导致的性能问题不是重点,重点是记录一些查找问题的过程与思路)