Java 非常大的堆大小

标签 java performance garbage-collection heap-memory

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

  • GC 是否使程序无法使用?
  • 您使用哪些 GC 参数?
  • 哪个 JVM、Sun 或 BEA 更适合这个?
  • Linux 或 Windows 哪个平台在这种情况下表现更好?
  • 在 Windows 的情况下,在如此高的内存负载下,64 位 Vista 和 XP 之间是否存在性能差异?

最佳答案

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

但是,当您需要保持低 GC 暂停时,事情会变得非常糟糕:

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

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

  3. 当 CMS 垃圾收集器在年老代填满之前不够快完成操作时,它会退回到标准的 stop-the-world GC。对于大小为 16 GB 的堆,预计会有大约 30 秒或更长时间的停顿。您可以尽量避免这种情况,使您的应用程序的长期垃圾产生率尽可能低。请注意,运行应用程序的核心数量越多,问题就越大,因为 CMS 只使用一个核心。显然,请注意 no 保证 CMS 不会退回到 STW 收集器。当它发生时,它通常发生在峰值负载时,你的应用程序会死掉几秒钟。您可能不想为此类配置签署 SLA。

  4. 嗯,有新的 G1 东西。理论上它是为了避免 CMS 的问题而设计的,但我们已经尝试过并观察到:

    • 它的吞吐量比 CMS 差。
    • 理论上它应该首先避免收集流行的内存块,但它很快就会达到几乎所有 block 都是“流行”的状态,并且它所基于的假设只是停止工作。
    • 最后,G1 的 stop-the-world 后备方案仍然存在;询问甲骨文,该代码应该何时运行。如果他们说“从不”,问他们,为什么代码在那里。所以恕我直言,G1 并没有真正解决 Java 的巨大堆问题,它只会让它(可以说)更小一些。
  5. 如果您有钱购买具有大内存的大型服务器,那么您可能也有钱购买优质的商业硬件加速、无暂停 GC 技术,例如 Azul 提供的技术。我们有一台具有 384 GB RAM 的服务器,它运行良好 - 没有停顿,GC 中有 0 行停止世界的代码。

  6. 用 C++ 编写需要大量内存的应用程序的该死部分,就像 LinkedIn 在社交图处理中所做的那样。这样做仍然无法避免所有问题(例如堆碎片),但保持低停顿肯定会更容易。

关于Java 非常大的堆大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/214362/

相关文章:

performance - 使用 EJB 的实例池如何提高性能?

c# - "Dispose"是否应该仅用于包含非托管资源的类型?

java - Java中类设计的最佳方式: An example

java - 传递 Java 谓词

css - 存储多个缩略图与使用 CSS

wpf - 在 WPF 中呈现非托管视频帧的最有效方法是什么?

javascript - JS 字符串/数字和垃圾回收

java - 加载大文件时超出 GC 开销限制

java - 如何使用 DateTimeFormatter 从 MONTH ("MMMM") 或 YEAR ("yyyy") 获取 Date 对象

java - Selenium - 写入网络驱动器。可以写入文本文件,但不能写入图像文件