优化 Java 对象以提高 CPU 高速缓存行效率

2022-09-04 03:24:47

我正在编写一个库,其中:

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

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

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

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


答案 1

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

为了避免引用,以下情况可能很明显:

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

这些规则至少可以确保在处理单个对象和遍历对象图中的对象引用时具有一定的参照局部性。

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

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

当然,这与你通常在JAVA中应该做的事情完全正交:)

此致敬意


答案 2

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

免责声明:图书馆的作者。


推荐