Java 非常大的堆大小 [已关闭]
有没有人有在Java中使用非常大的堆(12 GB或更高)的经验?
- GC 是否使程序不可用?
- 你们使用哪些 GC 参数?
- 哪种JVM,Sun或BEA更适合这样做?
- 在这种情况下,哪个平台(Linux或Windows)的性能更好?
- 在Windows的情况下,在如此高的内存负载下,64位Vista和XP之间是否存在任何性能差异?
有没有人有在Java中使用非常大的堆(12 GB或更高)的经验?
如果您的应用程序不是交互式的,并且 GC 暂停对您来说不是问题,那么 64 位 Java 处理非常大的堆(即使是数百 GB)应该不会有任何问题。我们也没有注意到Windows或Linux上的任何稳定性问题。
但是,当您需要保持GC暂停较低时,事情变得非常讨厌:
忘记默认吞吐量,停止世界 GC。对于中等堆(< ~30 GB),它会暂停您的应用程序数十秒,对于大型堆(> ~30 GB),它将暂停您的应用程序几分钟。购买更快的 DIMM 也无济于事。
最好的办法可能是CMS收集器,由-XX:+UseConcMarkSweepGC启用。CMS 垃圾回收器仅在初始标记阶段和注释阶段停止应用程序。对于非常小的堆,如< 4 GB,这通常不是问题,但对于创建大量垃圾和大堆的应用程序,注释阶段可能需要相当长的时间 - 通常比完全停止世界少得多,但对于非常大的堆来说仍然是一个问题。
当 CMS 垃圾回收器的速度不足以在终身制生成填满之前完成操作时,它将回退到标准的停止世界 GC。对于大小为 16 GB 的堆,预计会出现大约 30 秒或更长时间的暂停。您可以尽量避免这种情况,使应用程序的长期垃圾生产率尽可能低。请注意,运行应用程序的内核数越高,遇到此问题的次数就越大,因为 CMS 仅使用一个内核。显然,请注意,不能保证CMS不会回退到STW收集器。当它发生时,它通常发生在峰值负载时,并且您的应用程序会死几秒钟。您可能不希望为此类配置签署 SLA。
好吧,有一个新的G1的东西。从理论上讲,它旨在避免CMS的问题,但是我们已经尝试过并观察到:
如果你为一台内存大的大服务器花钱,你可能也为一个好的,商业硬件加速的,无暂停的GC技术,比如Azul提供的那个。我们有一台带有384 GB RAM的服务器,它确实可以正常工作 - 没有暂停,GC中的0行停止世界代码。
编写应用程序中需要大量内存的C++部分,就像LinkedIn社交图处理一样。您仍然无法通过执行此操作来避免所有问题(例如堆碎片),但是保持较低的暂停肯定会更容易。
我是Azul Systems的首席执行官,所以我对这个话题的看法显然有偏见!:)话虽如此...
Azul 的首席技术官 Gil Tene 很好地概述了与垃圾回收相关的问题,并在他的“了解 Java 垃圾收集和您可以对它做些什么”演示文稿中回顾了各种解决方案,本文中还有其他详细信息:http://www.infoq.com/articles/azul_gc_in_detail。
在我们的Zing JVM中,Azul的C4垃圾收集器是并行和并发的,并且对新旧两代使用相同的GC机制,在这两种情况下同时工作和压缩。最重要的是,C4没有停止世界后退。所有压缩都与正在运行的应用程序同时执行。我们有客户运行非常大的(数百 GB),更差情况下的 GC 暂停时间为 <10 毫秒,并且根据应用程序的不同,通常小于 1-2 毫秒。
CMS 和 G1 的问题在于,在某些时候必须压缩 Java 堆内存,并且这两个垃圾回收器都会停止 the-world/STW(即暂停应用程序)来执行压缩。因此,虽然CMS和G1可以推出STW暂停,但它们并不能消除它们。然而,Azul的C4确实完全消除了STW暂停,这就是为什么Zing即使对于巨大的堆大小也有如此低的GC暂停。