项目背景: 服务接收队列里头的数据,然后进行查询数据,计算,更新数据保存。所有的数据都是计算完即丢弃。计算的数据DTO 还是比较大的。
分析:发现数据YGC 比较频繁,平均4次/min,gc情况如下图:每分钟3次,每分钟:0.3秒。平均起来就是每个20秒YGC 一次。同时发现,Eden区每次GC之后内存几乎都节省出一个多G的内存。即Eden 去大部分的对象都是失效的数据。真正存活的对象只有20~30M而已。具体如下图:
疑问:对改计算的DTO使用对象池会如何?会不会节省GC时间,内存使用量是不是会有所下降?
在项目中引入对象池,然后动态的做了对象池的开关。然后试验结果如下:
左右两边的分别是未使用的对象池,和使用对象池。
1. 可以看到:未使用对象池,可使用内存大约1000M,使用对象池大约有3000M
2. GC 次数,时间反而比较多了?
(ps :运行几个小时之后,使用对象池的GC次数和时间比未使用对象池的略微好一些)
3. Eden 去为使用对象池时,GC效果明显,可回收的内存很多,使用对象池之后,GC 效果明显稍差,可回收的内存变少了许多,Old Gen 使用的空间明显变少了许多
原因是对象都放内存里头占用空间了。至于old Gen变少的原因是,计算的DTO对象过大,申请内存时大于阈值,所以直接被分配到老年代了
4. 使用磁盘的使用量明显升高了不少
5. 使用对象池CPU稍微的减少了一些,因为对象池减少了频繁的创建对象
5. 使用对象池内存稍微的减少了一些
最终的结论:
1. 使用对象池,可以减少内存,cpu的使用。 有利于控制系统资源。
2. 本次的场景中使用的对象池,并没有达到减少GC次数,也没有减少GC的时间。
事后分析,DTO里面充填的数据每次都是冲数据库查询出来的,每次查询都会New 一个新的对象,所以还是会频繁的创建对象,故没有达到对象复用的目的。
对象的介绍与使用详见:《对象池的介绍与使用》