java - 当工作集很小时,如何说服 Java 垃圾收集器运行?

标签 java garbage-collection

这是另一个“请告诉我如何强制 Java 垃圾收集器运行”的问题。在我们的应用程序中,我相信我们有充分的理由这样做。

这是一个服务器应用程序,通常有大约 500 万个 Activity 对象。每 5 分钟一次,我们执行一个大约需要 60 秒的分析任务。如果在分析运行时触发了完整的 GC,则将有大约 40M 的 Activity 对象。分析完成后,额外的 35M 对象变为垃圾。服务器必须始终保持对请求的响应(即使在分析运行时)。

我们发现,如果在分析未运行时调用完整的 GC 大约需要 1.5 秒,但在分析运行时大约需要 15 秒。不幸的是,我们的分配模式使得完整的 GC 通常在分析期间触发,即使分析只运行了 20% 的时间。 (每第三或第四次分析运行触发一次完整的 GC。)

如果老一代中的可用空间低于某个阈值 (5GB),我在开始分析运行之前添加了代码来调用备受鄙视的 System.gc()。好处是非常可观的:我们获得了 1.5 秒的暂停时间而不是 15 秒的暂停时间,并且我们将更多的垃圾释放到交易中。但是,有时 System.gc() 调用会被忽略,几分钟后自动触发 GC 时会出现 15 秒的暂停。

那么我的问题是:我们可以做些什么来更有力地说服垃圾收集器运行吗?我们正在运行 1.7.0_09-icedtea 并使用 Parallel GC。我想要(a)一种手动强制垃圾收集的可靠方法,或者(b)某种方式来调整收集器,以便它做出更智能的自动决策。 (b) 似乎很难,因为我不清楚收集器如何检测到我们的工作集以这种戏剧性的方式变化。

如果需要,我愿意求助于大量黑客;这对我们来说是一个严重的问题。 (我们可能会考虑 CMS 或 G1 压缩器作为替代方案,但我对 CMS 对吞吐量的影响持怀疑态度,而且 G1 被认为在我们使用的大字节数组面前表现不佳。)

附录:在生产中,到目前为止,我们的经验是 System.gc() 通常确实会触发完整的垃圾回收;至少,在我们调用它的情况下。 (我们每 10 到 30 分钟才调用一次,堆中有些但没有完全填满垃圾。)能够更可靠地触发垃圾收集会很好,但它在大多数情况下都在帮助我们。

最佳答案

您的问题是您在同一个 JVM 中运行两个具有完全不同要求和内存配置文件的应用程序。

在非面向用户的过程中单独运行数据分析,以便面向用户的服务器保持持续响应。我假设定期分析会生成某种摘要或结果数据;通过将其传送到面向用户的服务器使其可供最终用户使用,以便可以从那里提供服务,或者让您的前端从分析服务器中单独获取它。

关于java - 当工作集很小时,如何说服 Java 垃圾收集器运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19416198/

相关文章:

java - 复杂作业的 Spring Batch 性能改进

java - 不支持 Path.isConvex。 Android Studio - 切换按钮

javascript - 串联会产生垃圾吗?

java - 数组改组不起作用

java - 在 java 中解析此字符串的最佳方法?

java - GC 似乎导致 java 服务器应用程序无响应

java - 紧密循环中的 String.valueOf(Double) 会产生大量垃圾

node.js - 使用 VM 执行不受信任的代码时 NodeJS 内存泄漏

c# - 在 .NET 中固定内存对象的生命周期

c# - 我应该默认推荐密封类吗?