【问题标题】:Can i use more heap than 32 GB with compressed oops我可以在压缩 oops 中使用超过 32 GB 的堆吗
【发布时间】:2018-09-04 21:11:57
【问题描述】:

我可以理解,使用压缩的 oops,我们只能使用 32 GB 的 RAM。有没有办法我可以通过分配 2 个堆或其他东西来使用更多?

谢谢 藤蔓

【问题讨论】:

  • 不使用压缩 oops 怎么样?
  • 我正在尝试将大量日期值对存储到主存储器以进行高速访问。在这里,我应用了许多优化,最终 80% 的空间被引用而不是实际数据占用。为了减少引用占用的空间,我发现了压缩的 oops。

标签: java oop optimization compression


【解决方案1】:

您不能拥有多个堆(但您可以拥有多个 JVM,这称为向外扩展而不是向上扩展)。

JVM 自动使用低于 32 GiB 内存的压缩对象指针。如果您了解它是如何工作的(从每个地址中删除最年轻的三位,因为由于内存对齐,它们始终为 0),您就会明白您无法走得更远。

有一个有趣的事实:一旦超过这个 32 GiB 边界,JVM 就会停止使用压缩对象指针,从而有效地减少了可用内存。这意味着您必须将 JVM 堆增加到 32 GiB 以上。根据伟大的Everything I Ever Learned about JVM Performance Tuning @twitter(大约 13:00)演示将堆从 32 GiB 增加到 48 GiB 以下的任何内容实际上会减少可用内存量(!)因为压缩对象指针不再存在。

【讨论】:

  • 好吧,盈亏平衡点是 48GiB 是不正确的。确切的数字取决于您在内存中保存的指针数量。这对于每个应用程序都是不同的。
  • @RokKralj 你说得对,盈亏平衡将取决于每个应用程序。例如,如果您的应用程序主要是“2G 数组 int”Aka,8G,那么您将看到内存使用几乎没有差异。然而,对于“正常”使用模式,您最终会因较大的指针而产生大量额外开销。
【解决方案2】:

如果您需要超过 32 GB,我建议您考虑使用一些堆外内存。这有效地为您提供了一个不会占用太多堆的额外内存空间。

例如,我通常使用 200-800 GB,但其中只有 1-2 GB 是堆。这意味着我拥有最有效的压缩 Oops 形式和几乎无限的容量。注意:压缩的Oops有三种形式,

  • 普通 32 位非移位(最高约 2 GB)
  • 32 位移位(最高约 26 GB)
  • 32 位移位和偏移(最高约 32 GB)

使用堆外内存的两种方式是直接内存字节缓冲区和内存映射文件。直接内存可以扩展到大约主内存大小的 3/4。内存映射文件可以很好地扩展到您的硬盘空间大小(通常更多)

在这里我应用了许多优化,最终 80% 的空间被引用而不是实际数据占用。

听起来您没有使用最有效的数据结构。您可以使用不同的数据结构,其中数据使用的空间更多或至少 2/3。

【讨论】:

  • “我通常使用 200-800 GB”。我羡慕你……那是虚拟内存还是由实际 RAM 支持?
  • @Thilo 我使用虚拟内存,因为我只有 128 GB 的主内存,但我的一些客户有 512 GB 到 3 TB 的主内存。
【解决方案3】:

您可以通过附加参数使用更大的堆大小: -XX:ObjectAlignmentInBytes=alignment

这个参数是Java对象的固定调整。默认值为8(字节)。指示的值必须是 2 的幂,范围从 8256

以字节为单位的堆大小限制计算如下:

4GB * ObjectAlignmentInBytes

64GB 堆大小可用于压缩指针,如下所示:

-XX:ObjectAlignmentInBytes=16

在文档中需要考虑更大的堆大小的注意事项:

注意:随着对齐值的增加,之间的未使用空间 对象也会增加。结果,您可能没有意识到任何 受益于使用具有较大 Java 堆大小的压缩指针。

【讨论】:

    【解决方案4】:

    如果我站在你的立场上,我会调查以下各项:

    1. 不使用压缩 oops。
    2. 减少应用程序的内存消耗(内存分析器是调查内存使用情况的非常方便的工具)。
    3. 在多个 JVM 之间拆分工作负载,每个 JVM 都有一个低于 32GB 的堆。

    以上每一项都有可能解决您的问题。哪个最合适我们真的很难说。

    80% 的空间被引用而不是实际数据占用。

    这听起来相当极端。可能值得重新审视您的数据结构,重点是减少对象引用的数量。我过去曾按照这些思路进行过操作,但如果不了解您的问题和您当前使用的数据结构,很难给出具体的建议。

    【讨论】:

    • 我有 15000000000 个日期,值对要存储。我已经应用了最好的数据结构来获得最好的性能,但是参考就是吃空间的东西。 2 JVM是我想到的。如果有更好的想法,请告诉我。
    【解决方案5】:

    数据的本质是什么?

    执行此操作的方法可能是将数据存储在 Java 堆之外。您可以通过获取一些堆外内存来做到这一点,通常使用direct ByteBuffer,然后以字节的形式将数据存储在其中。这有很多优点;对象可以非常紧凑地存储,不需要很大的堆,并且对象不会被垃圾收集器清除。缺点是复杂,还有内存泄漏的风险。

    有一些库可以帮助您做到这一点,包括:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-13
      • 2022-09-29
      • 2011-12-26
      • 1970-01-01
      • 2022-06-20
      • 1970-01-01
      • 2011-09-01
      • 2010-12-16
      相关资源
      最近更新 更多