积极的垃圾回收器策略
我正在运行一个应用程序,该应用程序创建并忘记了大量对象,长期存在对象的数量确实增长缓慢,但与短期对象相比,这很少。这是一个具有高可用性要求的桌面应用程序,需要每天 24 小时打开。大部分工作都是在单个线程上完成的,这个线程将只使用它能得到的所有CPU。
过去,我们在重负载下看到过以下情况:随着垃圾回收器收集的内存量小于新分配的内存量,已用堆大小缓慢增长并最终接近指定的最大堆,已用堆空间缓慢上升。此时,垃圾回收器将大量启动并开始使用大量资源来防止超过最大堆大小。这会减慢应用程序的速度(很容易慢10倍),在这一点上,大多数时候GC会在几分钟后成功清理垃圾,或者失败并抛出一个,它们都不是真正可以接受的。OutOfMemoryException
使用的硬件是四核处理器,至少有4GB内存运行64位Linux,如果需要,我们可以使用所有这些。目前,该应用程序大量使用单个内核,该内核的大部分时间都在运行单个内核/线程。其他内核大多处于空闲状态,可用于垃圾回收。
我有一种感觉,垃圾收集器应该在早期阶段更积极地收集,远远早于它耗尽内存之前。我们的应用程序没有任何吞吐量问题,低暂停时间要求比吞吐量重要一些,但远不如不接近最大堆大小重要。如果单个繁忙线程仅以当前速度的 75% 运行,则是可以接受的,只要这意味着垃圾回收器可以跟上创建的速度。因此,简而言之,性能的稳步下降比我们现在看到的突然下降要好。
我已经彻底阅读了Java SE 6 HotSpot[tm] 虚拟机垃圾回收调整,这意味着我很好地理解了这些选项,但是我仍然发现很难选择正确的设置,因为我的要求与论文中讨论的内容略有不同。
目前,我正在使用带有选项的ParallelGC。这比时间比的默认设置好一点,但我有一种感觉,GC可以通过该设置运行得更多。-XX:GCTimeRatio=4
对于监控,我主要使用jconsole和jvisualvm。
我想知道您对上述情况建议哪些垃圾回收选项。另外,我可以查看哪些GC调试输出以更好地了解瓶颈。
编辑:我知道一个非常好的选择是创建更少的垃圾,这是我们真正考虑的事情,但是我想知道我们如何通过GC调整来解决这个问题,因为这是我们可以更容易地完成的事情,并且比更改大量源代码更快地推出。此外,我还运行了不同的内存分析器,并且我了解垃圾的使用方式,并且我知道它由可以收集的对象组成。
我正在使用:
java version "1.6.0_27-ea"
Java(TM) SE Runtime Environment (build 1.6.0_27-ea-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.2-b03, mixed mode)
使用 JVM 参数:
-Xmx1024M and -XX:GCTimeRatio=4
编辑回复 Matts 的评论:大多数内存(和cpu)用于构造表示当前情况的对象。随着情况的快速变化,其中一些将被立即丢弃,而另一些则如果一段时间内没有更新,则会有一个中等寿命。