【问题标题】:Extremely long garbage collection times极长的垃圾收集时间
【发布时间】:2012-06-26 01:54:15
【问题描述】:

我们有一个运行 Java 6、Tomcat 6、Spring Framework 3、Hibernate 4、EhCache 的 Web 应用程序。 我们遇到了一个垃圾收集时间过长的问题,可能需要 30 秒或更长时间,导致应用程序无响应。

我们目前正在测试中,但除了明显的:添加更多内存之外,我想知道是否可以调整某些方面来减少垃圾收集时间。

内存使用的主要贡献者是 EHCache,因为我们正在积极缓存。但是我总是发现很难调整 EHCache 存储的大小(新的 EhCache 字节大小存储会给我们带来各种问题,因为缓存的对象图可能非常大)。

这些是我对 JVM 的设置

JAVA_OPTS="$JAVA_OPTS -server -Xms256m -Xmx704m XX:OnOutOfMemoryError=/usr/share/scripts/on_server_crash.sh -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/tomcat6 -XX:MaxPermSize=192m -XX:+UseConcMarkSweepGC

【问题讨论】:

  • 在内存达到最大值 704MB 之前,您是否得到了这么长时间?在决定增加使用的内存之前,JVM 在尝试减少使用的内存(并可能重新定位它)时可能有点“激进”。如果您使用 -Xms704m -Xmx704m 启动,它的行为是否相同?
  • 使用“jstat -gc 1s pid”你可以看到你的内存使用量是否达到了nurseries,或者是否应该改变nurseries、eden和old之间的内存分配。
  • 没有使用 JProdilfer/Yourkit 分析您的应用程序,您不会有任何可靠的建议。
  • 当然,理想的解决方案是并发GC。但只有少数实现。
  • @Roger setting -Xms704m -Xmx704m 似乎确实有点帮助,但很难说。仍然需要超过 25 秒。我将 EHCache 设置设置为 diskoverflow="true"。我想知道问题是否与大量磁盘读/写有关。盒子上的内存似乎或多或少还可以:

标签: java garbage-collection jvm


【解决方案1】:

要减少 GC 时间,最好的办法是使用堆外内存。如果您可以移动尽可能多的大数据,即使使用 100 MB 的堆外内存,您也可以将完整的 GC 时间减少到低至 10 毫秒。我相信 Ehcache 支持堆外数据存储,但如果它不支持或者你不能使用它,我建议你看看替代方案。

鉴于您只有 700 MB 的最大内存大小,您似乎在内存非常有限的服务器上运行。否则,我建议您从最大 8 或 16 GB 开始,如果您认为自己不需要它,请减小内存大小。

【讨论】:

  • 内存大小不应该成为 GC 时间的问题。只有在 GC 开始之前创建的对象数。
  • @user2763361 对象的数量非常重要,其他因素也很重要,例如引用的数量以及这些引用的生成,但它是您可以在监控工具中看到的大小。如果减少消耗的内存,则可以提高性能,因为这通常意味着减少对象的数量和引用间接的数量。简而言之,您是对的,但内存使用量更容易衡量。
【解决方案2】:

FourSquare 提供了一款出色的工具。检查此链接和他们拥有的快速示例。 Foursquare Heap tool. 。根据您在上述任何工具中找到的诊断结果,解决问题的最有序解决方案将是添加更多 RAM 或增加 CPU 处理器的功率。如果您愿意接受一些基础架构更改,请查看 Zing from Azul Systems。但我认为第二种选择可能有点牵强。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-28
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多