14

我正在写一个库,其中:

  • 它将需要在各种不同的平台/Java 实现上运行(常见的情况可能是带有 Windows 或 Linux 的 Intel 64 位机器上的 OpenJDK 或 Oracle Java)
  • 在我关心对象访问中的 CPU 缓存线效率的情况下,实现高性能是一个优先事项
  • 在某些区域,将遍历/处理相当大的小对象图(假设大约 1GB 规模)
  • 主要工作量几乎完全是读取
  • 读取将分散在对象图中,但不是完全随机的(即会有明显的热点,偶尔读取访问频率较低的区域)
  • 对象图将被多个线程同时访问(但不修改)。假设不会发生并发修改,则没有锁定。

是否有一些设计小对象的经验法则/指南,以便它们在这种环境中有效地利用 CPU 缓存线?

我对正确调整对象的大小和结构特别感兴趣,以便例如最常访问的字段适合第一个缓存行等。

注意:完全意识到这取决于实现,我需要进行基准测试,以及过早优化的一般风险。无需浪费任何进一步的带宽来指出这一点。:-)

4

2 回答 2

11

实现高速缓存行效率的第一步是提供参考局部性(即保持数据彼此靠近)。这在几乎所有东西都是系统分配和通过引用访问的 JAVA 中很难做到。

为了避免引用,以下内容可能很明显:

  1. 将非引用类型(即 int、char 等)作为对象中的字段
  2. 将对象保存在数组中
  3. 保持你的小物件

在处理单个对象和遍历对象图中的对象引用时,这些规则至少会确保一些引用局部性。

另一种方法可能是根本不为您的数据使用对象,而是为每个通常是类中的字段的项目使用全局非引用类型数组(大小相同),然后每个实例将由一个公共索引标识到这些数组中。

然后,为了优化数组或其块的大小,您必须了解 MMU 特性(页面/缓存大小、缓存行数等)。我不知道 JAVA 是否在 System 或 Runtime 类中提供此信息,但您可以在启动时将此信息作为系统属性传递。

当然,这与您通常应该在 JAVA 中执行的操作完全正交 :)

此致

于 2012-12-31T03:31:04.287 回答
2

您可能需要有关 CPU 的各种缓存的信息,您可以使用Cachesize(当前支持 Intel CPU)从 Java 访问它。这有助于开发缓存感知算法。

免责声明:lib 的作者。

于 2014-01-12T17:26:42.290 回答