JVM 压缩 Oops 背后的技巧

2022-01-16 00:00:00 jvm memory-management java

所以我知道 HotSpot VM 现在默认启用压缩 oops.从 Java SE 6u23 开始,它通过 VM 选项 -XX:+UseCompressedOops 对此提供了支持.我知道它允许有效地利用 CPU 缓存,因为 CPU 缓存可以容纳更多的引用,而不是它们必须处理 64 位大小的引用.但我不明白的是,仅使用 32 位 JVM 可以寻址多达 264 个地址.

So I understand the compressed oops is enabled by default in HotSpot VM now. It has support for this from Java SE 6u23 onwards through the VM option -XX:+UseCompressedOops. I understand that it allows for efficient CPU cache utilization as the CPU caches can hold a larger number of references than if they had to deal with 64 bit sized references. But what I do not understand is how using only 32 bits JVM can address up to 264 addresses.

为了简化问题,我们如何仅使用 2 位寻址多达 24 个内存地址?这种地址方案的可能编码/解码是什么?

To simplify the problem how can we address up to 24 memory address's using just 2 bits? What can be a possible encoding/decoding of such an address scheme?

推荐答案

压缩oops的详细解释见Hotspot JVM 中的压缩 oops" 文章,作者 John Rose @ Oracle.

For a detailed explanation of compressed oops, see the "Compressed oops in the Hotspot JVM" article by John Rose @ Oracle.

TL;DR 版本是:

  • 在现代计算机架构中,内存地址是字节地址,
  • Java 对象引用是指向单词开头的地址1,
  • 在 64 位机器上,字对齐意味着对象引用/地址的低 3 位为零2
  • 因此,通过将地址向右移动 3 位,我们可以将 64 位地址的最多 35 位压缩"为 32 位字,
  • 而且,解压缩可以通过左移 3 位来完成,这会将这 3 个零位放回原处,
  • 35 位寻址允许我们使用适合 64 位机器上 32 位(半)字的压缩 oop 来表示最多 32 GB 堆内存的对象指针.

请注意,这仅适用于 64 位 JVM.我们仍然需要能够寻址包含(最多)32 GB 堆的内存1,这意味着 64 位硬件地址(在现代 CPU/计算机架构上).

Note that this only works on a 64-bit JVM. We still need to be able to address the memory containing that (up to) 32 GB heap1, and that means 64-bit hardware addresses (on modern CPUs / computer architectures).

还请注意,这样做会有一点点惩罚;即在常规和压缩引用之间转换所需的移位指令.但是,另一方面是消耗的实际内存更少3,因此内存缓存通常更有效.

Note also that there is a small penalty in doing this; i.e. the shift instructions required to translate between regular and compressed references. However, the flip side is that less actual memory is consumed3, and memory caches are typically more effective as a consequence.

1 - 这是因为现代计算机架构针对字对齐内存访问进行了优化.

2 - 这假设您没有使用 -XX:ObjectAlignmentInBytes 来增加其默认(和最小值)8 字节的对齐值.

2 - This assumes that you haven't used -XX:ObjectAlignmentInBytes to increase the alignment from its default (and minimum) value of 8 bytes.

3 - 事实上,内存节省是特定于应用程序的.它取决于平均对象对齐损耗、参考与非参考字段的比率等.如果您考虑调整对象对齐,它会变得更加复杂.

为了简化问题,我们如何仅使用 2 位寻址多达 24 个内存地址?这种地址方案的可能编码/解码是什么?

To simplify the problem how can we address up to 24 memory addresses using just 2 bits? What can be a possible encoding/decoding of such an address scheme?

您不能寻址 24 字节地址.但是您可以使用 2 位字地址寻址 22 个字地址(假设为 32 位字).如果您可以假设所有字节地址都是字对齐的,那么您可以将 4 位字节地址压缩为 2 位字地址,方法是将其移动 2 位位置.

You can't address 24 byte addresses. But you can address 22 word addresses (assuming 32-bit words) using 2-bit word addresses. If you can assume that all byte addresses are word-aligned, then you can compress a 4-bit byte address as 2-bit word address by shifting it by 2-bit positions.

相关文章