优化Java对象以提高CPU缓存行的效率
我正在写一个库,其中:
- 它需要在各种不同的平台 / Java实现上运行(常见的情况可能是使用Windows或Linux的Intel 64位计算机上的OpenJDK或Oracle Java)
- 实现高性能是一个优先事项 ,因为我关心对象访问中的CPU缓存行效率
- 在某些区域,将遍历/处理相当大的小对象图形 (假设大约1GB)
- 主要工作量几乎完全是读取
- 读取将分散在对象图中,但不是完全随机的(即,将存在重要的热点,偶尔读取到不常访问的区域)
- 多个线程将同时访问 (但不修改)对象图。 没有锁定,假设不会发生并发修改。
设计小对象是否有一些经验法则/指南,以便在这种环境中有效利用CPU缓存线?
我对正确调整和构造对象特别感兴趣,因此例如最常访问的字段适合第一个缓存行等。
注意:我完全清楚这是依赖于实现的,我需要进行基准测试,以及过早优化的一般风险。 无需浪费任何进一步的带宽指出这一点。 🙂
高速缓存行效率的第一步是提供参考局部性(即保持数据彼此接近)。 这在JAVA中很难做到,几乎所有东西都是通过引用分配和访问的系统。
为避免引用,以下内容可能很明显:
- 将非引用类型(即int,char等)作为对象中的字段
- 将对象保存在数组中
- 保持你的对象小
在处理单个对象和遍历对象图中的对象引用时,这些规则至少会确保一些引用局部性。
另一种方法可能是根本不使用对象作为数据,但是对于通常是类中的字段的每个项具有全局非ref类型数组(大小相同),然后每个实例将由公共索引标识进入这些数组。
然后,为了优化arrays或其块的大小,您必须知道MMU特性(页面/高速缓存大小,高速缓存行数等)。 我不知道JAVA是否在System或Runtime类中提供了这个,但您可以在启动时将此信息作为系统属性传递。
当然,这与你在JAVA中通常应该做的完全正交:)
最好的祝福
您可能需要有关CPU的各种高速缓存的信息,您可以使用Cachesize (当前支持Intel CPU)从Java访问它。 这有助于开发缓存感知算法。
免责声明:lib的作者。