Java垃圾收集导致延迟影响性能

时间:2013-05-13 01:10:04

标签: java performance garbage-collection

我注意到我的应用程序中存在一种奇怪的现象。我将对象提交到服务器后将其存储在Hashmap中,并在响应到达时将其删除。

我最近注意到跑步后性能非常慢。检查后,我发现内存使用率保持在4GB,然后下降到小于1 GB。我怀疑它正在清理很多对象,这就是性能变得如此糟糕的原因。

所以问题是为什么Java收垃圾收集这么晚了?也就是说,为什么要等到堆满了然后再进行垃圾收集呢?不应该定期收集垃圾。

存储在HashMap中的对象就是在那个时候创建​​的,也就是说它们不会长久存在。

这是在Linux(RHEL),Oracle JVM HotSpot 7. 64位上。 4核心。这就是应用程序的运行方式:

java -jar -Xmx4g prog.jar

注意:我已经看到了这一点:Tuning garbage collections for low latency但是现在我想了解为什么GC需要这么长时间才能启动?

3 个答案:

答案 0 :(得分:3)

听起来你有两个问题之一:

  1. 如果你有半长寿命的物体,他们将从年轻一代转移到更老的一代(如HotSpot到Mark-Compact generation。)也就是说,他们将停止被引用计入收集并开始存在保留较慢的GC。
  2. 您的年轻一代堆空间太小,不适合您的使用模式,迫使对象从年轻一代转移到老一代。
  3. 我会把你的年轻一代调整得更大。请参阅Generational Garbage Collection并查看各种类型的代。

答案 1 :(得分:1)

  

所以问题是为什么Java收垃圾收集这么晚了?也就是说,为什么要等到堆满了然后再进行垃圾收集呢?不应该定期收集垃圾。

您正在使用“吞吐量”垃圾收集器,这就是收集器的行为方式。它旨在通过最小化执行垃圾收集所花费的CPU时间百分比来最大化系统吞吐量。它通过等待堆(或更确切地说,新对象空间)已满的简单策略来实现。在所有条件相同的情况下,最有效的是:

  • 当你有很多垃圾时收集垃圾,
  • 在垃圾收集时停止其他一切。

(要了解原因,您需要了解复制收藏家的工作方式的技术细节......)

当然,这意味着你会有重大的停顿。

如果您想要低延迟,则需要使用其他收集器。但是,这会导致更多的实际CPU时间用于垃圾收集......以及其他与GC相关的开销。


如果您遇到很多重大停顿,那么空间的相对大小也可能存在问题。但是在你弄清楚相关参数之前,建议你打开GC记录,试着找出造成暂停的原因和频率。

答案 2 :(得分:0)

这只是因为除非堆已满,否则默认的GC不会启动。

JVM选择的默认垃圾收集器是Parallel GC。它的目标是在尽可能短的停止世界暂停期间释放尽可能多的内存。除非伊甸园已满,否则它不会在年轻一代开始。同样,除非Tenured已满,否则它不会在老一代开始。

如果要定期清理内存,可以切换到CMS。只需使用标志-XX:+UseConcMarkSweepGC即可。但是,这将意味着您的应用程序的一些开销。这是让GC定期运行而不暂停应用程序的成本。

所以,总结一下:

  • 并行GC暂停应用程序,仅在没有其他选择时启动

  • CMS并发运行而不会暂停您的应用程序,但有一些开销

来源:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html