Java 非常大的堆大小 [已关闭]

有没有人有在Java中使用非常大的堆(12 GB或更高)的经验?

  • GC 是否使程序不可用?
  • 你们使用哪些 GC 参数?
  • 哪种JVM,Sun或BEA更适合这样做?
  • 在这种情况下,哪个平台(Linux或Windows)的性能更好?
  • 在Windows的情况下,在如此高的内存负载下,64位Vista和XP之间是否存在任何性能差异?

答案 1

如果您的应用程序不是交互式的,并且 GC 暂停对您来说不是问题,那么 64 位 Java 处理非常大的堆(即使是数百 GB)应该不会有任何问题。我们也没有注意到Windows或Linux上的任何稳定性问题。

但是,当您需要保持GC暂停较低时,事情变得非常讨厌:

  1. 忘记默认吞吐量,停止世界 GC。对于中等堆(< ~30 GB),它会暂停您的应用程序数十秒,对于大型堆(> ~30 GB),它将暂停您的应用程序几分钟。购买更快的 DIMM 也无济于事。

  2. 最好的办法可能是CMS收集器,由-XX:+UseConcMarkSweepGC启用。CMS 垃圾回收器仅在初始标记阶段和注释阶段停止应用程序。对于非常小的堆,如< 4 GB,这通常不是问题,但对于创建大量垃圾和大堆的应用程序,注释阶段可能需要相当长的时间 - 通常比完全停止世界少得多,但对于非常大的堆来说仍然是一个问题。

  3. 当 CMS 垃圾回收器的速度不足以在终身制生成填满之前完成操作时,它将回退到标准的停止世界 GC。对于大小为 16 GB 的堆,预计会出现大约 30 秒或更长时间的暂停。您可以尽量避免这种情况,使应用程序的长期垃圾生产率尽可能低。请注意,运行应用程序的内核数越高,遇到此问题的次数就越大,因为 CMS 仅使用一个内核。显然,请注意,不能保证CMS不会回退到STW收集器。当它发生时,它通常发生在峰值负载时,并且您的应用程序会死几秒钟。您可能不希望为此类配置签署 SLA。

  4. 好吧,有一个新的G1的东西。从理论上讲,它旨在避免CMS的问题,但是我们已经尝试过并观察到:

    • 它的吞吐量比CMS差。
    • 从理论上讲,它应该首先避免收集流行的内存块,但是它很快就会达到几乎所有块都“流行”的状态,并且它所基于的假设只是停止工作。
    • 最后,G1的停止世界回退仍然存在;问 Oracle,当代码应该运行时。如果他们说“从不”,问问他们,为什么代码在那里。所以恕我直言,G1真的不会让Java的巨大堆问题消失,它只会让它(可以说)变得更小。
  5. 如果你为一台内存大的大服务器花钱,你可能也为一个好的,商业硬件加速的,无暂停的GC技术,比如Azul提供的那个。我们有一台带有384 GB RAM的服务器,它确实可以正常工作 - 没有暂停,GC中的0行停止世界代码。

  6. 编写应用程序中需要大量内存的C++部分,就像LinkedIn社交图处理一样。您仍然无法通过执行此操作来避免所有问题(例如堆碎片),但是保持较低的暂停肯定会更容易。


答案 2

我是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暂停。


推荐