生产环境中的 Java G1 垃圾回收

2022-08-31 11:10:12

由于Java 7将默认使用新的G1垃圾回收,那么Java是否能够处理一个数量级更大的堆,而不会出现所谓的“毁灭性”GC暂停时间?有没有人真正在生产中实现G1,你有什么经验?

公平地说,我唯一一次看到真正长的GC暂停是在非常大的堆上,远远超过工作站。澄清我的问题;G1 会打开数百 GB 堆的网关吗?结核病?


答案 1

我一直在用一个繁重的应用程序测试它:60-70GB分配给堆,20-50GB随时使用。对于这些类型的应用程序,说您的里程可能会有所不同是轻描淡写的。我在 Linux 上运行 JDK 1.6_22。次要版本很重要 - 在大约1.6_20之前,G1中存在导致随机NullPointerExceptions的错误。

我发现它非常善于保持在你大部分时间给它的暂停目标之内。默认值似乎是100ms(0.1秒)的暂停,我一直告诉它做一半(-XX:MaxGCPauseMillis=50)。但是,一旦内存变得非常少,它就会惊慌失措并进行完全停止世界垃圾回收。使用65GB,这需要30秒到2分钟。(CPU的数量可能没有区别;它可能受到总线速度的限制。

与CMS(它不是默认的服务器GC,但它应该用于Web服务器和其他实时应用程序)相比,典型的暂停更具可预测性,并且可以缩短。到目前为止,我在CMS的巨大停顿方面运气更好,但这可能是随机的;我每24小时只看到他们几次。我不确定目前哪一个更适合我的生产环境,但可能是G1。如果甲骨文继续调整它,我怀疑G1最终将成为明显的赢家。

如果你对现有的垃圾回收器没有问题,那么现在没有理由考虑G1。如果您正在运行低延迟应用程序,例如GUI应用程序,G1可能是正确的选择,MaxGCPauseMillis设置得非常低。如果您正在运行批处理模式应用程序,G1 不会为您购买任何东西。


答案 2

听起来G1的要点是具有较小的暂停时间,甚至达到它能够指定最大暂停时间目标的程度。

垃圾回收不仅仅是一个简单的“嘿,它已满,让我们一次移动所有内容并重新开始”的交易 - 它是非常复杂的多级后台线程系统。它可以在后台进行大部分维护,而完全没有暂停,并且它还使用系统在运行时的预期模式的知识来提供帮助 - 就像假设大多数对象在创建后立即死亡一样,等等。

我想说的是,随着未来的发布,GC暂停时间将继续改善,而不是恶化。

编辑:

在重读时,我突然想到我每天都在使用Java-Eclipse,Azureus和我开发的应用程序,自从我看到暂停以来已经很久了。这不是一个明显的停顿,但我的意思是任何停顿。

当我右键单击Windows资源管理器或(偶尔)当我连接某些USB硬件时,我看到了暂停,但是使用Java---根本没有。

GC是否仍然与任何人有问题?