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

当工作集很小时,如何说服Java垃圾收集器运行?,java,garbage-collection,Java,Garbage Collection,这是另一个“请告诉我如何强制Java垃圾收集器运行”的问题。在我们的应用程序中,我相信我们有充分的理由这样做 这是一个服务器应用程序,通常有大约500万个活动对象。我们每5分钟执行一次分析任务,耗时约60秒。如果在分析运行时触发完整GC,将有大约4000万个活动对象。当分析完成时,额外的3500万个对象变成了垃圾。服务器必须始终对请求保持响应(即使在分析运行时) 我们发现,如果在分析未运行时调用完整GC,则需要大约1.5秒,但在分析运行时大约需要15秒。不幸的是,我们的分配模式是,在分析过程中通

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

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

我们发现,如果在分析未运行时调用完整GC,则需要大约1.5秒,但在分析运行时大约需要15秒。不幸的是,我们的分配模式是,在分析过程中通常会触发完整的地面军事系统,即使分析仅在20%的时间内运行。(每运行三次或四次分析就会触发一次完整GC。)

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

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

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


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

我想提供一个可能的替代方案,而不是直接回答您的问题(我不能)

这听起来像是在分析运行期间分配了大量大字节数组,然后允许在运行结束时对它们进行垃圾收集(或者试图在下一次运行之前强制对它们进行垃圾收集)

相反,如果可能的话,请尝试管理您自己的字节数组池,这样,在最好的情况下,您可以在应用程序第一次启动时分配所有需要的数组一次,然后它们在应用程序的整个生命周期内都有效,而不需要进行垃圾收集

当然,这个想法可以扩展到更复杂的数据结构和对象实例


这比在需要时分配内存和在不需要时“释放”内存要多得多,但应该大大减少垃圾收集器需要做的工作。

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


在非面向用户的流程中单独运行数据分析,以便面向用户的服务器始终保持响应。我假设定期分析生成某种类型的摘要或结果数据;通过将其传送到面向用户的服务器,使其可供最终用户使用,以便从那里获得服务,或者让您的前端从分析服务器中单独获取。考虑使用非托管内存,即,
ByteBuffer
s代替字节数组


我只能提供一个需要一些调整,然后可能会或可能不会工作的黑客。我会先尝试更理智的解决方案。当您想要强制GC时,可以通过分配大量内存来实现。这样做可以立即回收内存,但不能优化整个分配(类似于
sum+=newbyte[123456].hashCode()
应该这样做)。您需要找到一种可靠的方法来确定何时停止。带有终结器的对象可能会告诉您,或者可能会观看
运行时。getFreeMemory
可能会有所帮助。

我发现java GC处理大量对象(20-100m个对象)的能力非常差。 如果这些对象真的还活着,情况会更糟,因为即使没有什么可收集的,GC也会很可怕

解决方案是减少对象的数量(而不是使用的总内存)。 我敢猜测,您的分析阶段正在使用集合和许多基本包装(整数、长等)。 如果是这种情况,一种解决方案是切换到基本集合库。 我创建了一个这样的库来解决一个类似的问题,我在很长一段时间里用100万个活动对象进行了模拟。
该库被称为,有关详细信息,请参见wiki。

您显然已经完成了您的研究!我希望你得到一个好的答案;我也很想了解更多这方面的信息!我经常想知道这一点——强制垃圾收集是有正当理由的,尽管它们似乎非常非常罕见。也许我们需要一个特殊的JVM,里面有一个GC钩子。你试过把堆缩小吗?@HotLicks:我们没有试过缩小堆。你有理由认为这会有帮助吗?我的短裤