Ste*_*eve 22 java garbage-collection
这是另一个"请告诉我如何强制Java垃圾收集器运行"的问题.在我们的申请中,我认为我们有充分的理由这样做.
这是一个服务器应用程序,通常有大约500万个活动对象.每5分钟一次,我们执行一项需要约60秒的分析任务.如果在分析运行时触发了完整的GC,则会有大约40M的活动对象.分析完成后,额外的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)看起来很难,因为我不清楚收藏家如何发现我们的工作集以这种戏剧性的方式变化.
如果需要,我愿意诉诸大量的hackery; 这对我们来说是一个严重的问题.(我们可能会将CMS或G1压缩机视为替代方案,但我对CMS的吞吐量影响持怀疑态度,并且G1在我们使用的大字节数组面前表现不佳.)
附录:在生产中,我们迄今为止的经验是System.gc()通常会触发完整的垃圾收集; 至少,在我们称之为的情况下.(我们每10到30分钟只调用一次,堆有点但不完全充满垃圾.)能够更可靠地触发垃圾收集会很好,但它在大多数时候都在帮助我们.
小智 6
您的问题是您在同一JVM中运行两个具有完全不同要求和内存配置文件的应用程序.
在非面向用户的过程中单独运行数据分析,以便面向用户的服务器始终保持响应.我假设定期分析生成某种摘要或结果数据; 通过将其发送到面向用户的服务器,使其可供最终用户使用,以便从那里进行服务,或者让您的前端从分析服务器单独获取它.
我不想直接回答你的问题(我不能),而是想提供一个可能的替代方案。
听起来您在分析运行期间分配了大量的大字节数组,然后允许它们在运行结束时进行垃圾收集(或尝试强制它们在下一次运行之前进行垃圾收集)。
相反,如果可能的话,尝试管理自己的字节数组池,这样,在最好的情况下,您可以在应用程序首次启动时分配所有所需的数组一次,然后它们在应用程序的整个生命周期中都存在,并且不要不需要垃圾收集。
当然,这个想法可以扩展到更复杂的数据结构和对象实例。
这比仅仅在需要时分配内存并在不需要时“释放”内存要多做很多工作,但应该会大大减少垃圾收集器需要完成的工作。