【问题标题】:Are objects prefetched from an array of references in Java?对象是从 Java 中的引用数组中预取的吗?
【发布时间】:2015-09-22 21:43:51
【问题描述】:

假设我们有 1000 个相同类型的对象分散在内存中(它们是在不同时间创建的,而其他对象是在其间创建的)。

我们有一个数组,其中包含对 1000 个对象中每一个的引用。

问题

如果我们按顺序遍历数组,什么会被预取到 CPU 的缓存中?只有数组持有的引用还是这些引用会被取消引用并且对象也会被加载到缓存中?

Java(JVM)是​​否实现了某种软件预取?如果没有,是否有提供软件预取的库?

【问题讨论】:

  • 听起来好像是特定于实现的。我也坚信这取决于软件,因为memory ordering 可能会影响这些事情。不过,最后一部分可能是错误的。
  • 我很确定 CPU 缓存 100% 受硬件控制。当垃圾收集器工作时,它可能会将您的 1000 个对象合并到一个公共内存区域。然而,我读过的任何内容都没有表明任何 GC 都会这样做。无论如何,硬件缓存通常都充满了重要数据,任何“预缓存”都仅限于一个缓存行,通常约为 32-16 字节。
  • Heap分为young和old空间。young空间有最近分配的对象。当这些对象变老时,它们会转移到old区。“keep”是最近分配的地方快速移动且不会被垃圾收集的对象。
  • 我认为任何 CPU 都不会预取引用。这是没有意义的,因为如果您的对象的字节大小模 64(缓存行通常为64 byte long)相对较小,您会丢失很多缓存(总体而言,这可能会减慢您的程序)。此外,CPU 需要分析您的代码,以查看您是实际使用引用后面的对象还是仅使用引用(请记住,同一个 CPU 可能运行 C/C++ 代码)。
  • 不。这对 Java 来说是一个严重的性能问题。这就是为什么他们试图在 java9(或更高版本)中添加“值类型”,以便一个数组位于同一内存区域。

标签: java jvm jvm-hotspot prefetch java-memory-model


【解决方案1】:

经过一番研究,最常见的 JVM 实现(HotSpot)曾经 support prefetching。但是这个has been removed,因为它们没有实际用途。感谢@apangin 提供错误报告的链接。

正如@markspace 所提到的,对象会重新排列,以便在收集期间更容易访问 - 这称为“压缩”,并且存在于 HotSpot 使用的默认 GC 中。您不必担心这些底层细节,因为 VM 会为您处理这些。

更深入地了解压缩..

您可能听说过“Stop-The-World” - 当对象图处于不一致状态时会发生这种情况。对象正在四处移动,因此线程可能会访问不再存在的对象。有一些 GC 实现被认为是“无暂停”的,例如 Shenandoah GC,它使用转发指针来允许线程访问最近移动的对象。

重点是,您无需担心对象在内存中的位置,或者该位置与另一个对象的距离。 VM 旨在为您处理这些决定。

最终答案

那么,对象是从引用数组中预取的吗? 你真的不应该担心它。您使用 Java 不必关心这些底层细节。

如果您真的对这些细节感兴趣(也许您遇到了一些奇怪的错误),正如我之前提到的,它是特定于实现的,您必须具体说明您所指的实现到。

虽然,就像我之前说的,它是 Java;停止担心你不需要担心的事情。这一点我怎么强调都不过分。

【讨论】:

  • 同意。 Java 的要点是您(大多数时候)不必关心这些低级别的细节。 JIT 经过数千个项目和人员的经验培训,以使 Java 代码高效运行。将时间和精力投入到一个地方,以释放数百万开发人员的脑力。
  • 我已经 answered here 关于 HotSpot JVM 中的预取支持。但是,最近这些内在函数已从 HotSpot 开发存储库中完全删除,理由是它们没有实际用途。
  • @apangin 有道理。您是否有指向此信息来源的链接?还是没有记录
  • 这里是对应的bug link
猜你喜欢
  • 2012-02-05
  • 2015-02-05
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
  • 2020-05-04
  • 2014-05-14
  • 1970-01-01
相关资源
最近更新 更多