为什么长时间运行的高容量Java应用程序的GC时间会稳定增加?

时间:2010-09-09 08:55:15

标签: java garbage-collection jvm

我有一个高容量Java应用程序,可以处理50000msgs /秒的一致负载。它使用以下设置进行了高吞吐量调整:

-Xmx3g -Xms3g -XX:NewSize = 2g -Xss128k -XX:SurvivorRatio = 6 -XX:TargetSurvivorRatio = 90 -XX:+ UseParallelGC -XX:ParallelGCThreads = 12 -XX:+ UseParallelOldGC -XX:+ HeapDumpOnOutOfMemoryError

虽然GC的运行频率保持不变,但我发现年轻的GC时间从50毫秒开始稳步上升到当天结束时的200毫秒。

如果我使用ParNewGC收集器尝试相同的运行,GC时间会以更快的速度上升。有没有人对这个问题有任何想法?

2 个答案:

答案 0 :(得分:3)

如果您有内存泄漏,或内存缓存逐渐使用越来越多的内存,这些会导致GC执行更多工作来跟踪可访问的对象。

其他可能性是:

  • 您有非堆内存泄漏,这导致增加分页;即将物理内存页面复制到光盘和后面。

  • 某些外部进程正在消耗越来越多的内存,导致分页越来越多。

  • 年轻一代中生成的对象的性质随着时间的推移而变化,因此需要更多的工作来跟踪可到达的对象。可能只是因为其中较大比例的人在第一次收集后幸存下来。

答案 1 :(得分:2)

这可能是几个因素的组合:

  • 真正的内存泄漏。 (对象仍然偶然引用)
  • 更多对象,或者可能是gc池之间对象的不同分布。
  • 堆更大。绘制gc-time和堆大小。
  • 内存碎片。在OS级别和/或java堆上,具体取决于jvm。

为什么不绘制对象数量,堆大小和gc-time。 (使用工具,或通过查询MBean)情节应该告诉你趋势;增加,减少或线性,并将帮助您确定是否有泄漏。如果可能,还要从您的程序中转储一些统计信息,例如已处理的消息数或活动会话等。

这是一个真正的问题,因为你的消息在gc期间没有得到处理吗?尝试并发标记和扫描gc ......

* -XX:+UseConcMarkSweepGC -XX:+UseParNewGC