我正在写一个库,其中:
它需要在各种不同的平台/ Java实现上运行(常见的情况可能是带有Windows或Linux的Intel 64位计算机上的OpenJDK或Oracle Java)
在我关心对象访问中的CPU缓存行效率方面,实现高性能是当务之急
在某些区域,将遍历/处理相当大的小对象图(假设约为1GB的比例)
主要工作量几乎全部是读取
读取将分散在对象图中,但不会完全随机(即会有很大的热点,偶尔会读取访问频率较低的区域)
对象图将由多个线程同时访问(但不能修改)。假设不会发生并发修改,则没有锁定。
是否有一些设计小对象的经验法则/准则,以便它们在这种环境中有效地利用CPU缓存行?
我对正确调整对象的大小和结构特别感兴趣,例如最常访问的字段适合第一个缓存行等。
注意:我完全意识到这取决于实现,需要进行基准测试以及过早优化的一般风险。无需浪费任何进一步的带宽指出这一点。 :-)
我对该应用程序使用Java的基本原理感到好奇。您将在使语言接近要控制的数据布局的每一步中与语言作斗争。该控制程度对于实现例如在C ++中。
对不起,我认为那是你必须放弃的野心。 :)在更高版本中(我不记得确切的开始时间),Hotspot将重新安排类的内部结构,以适合您认为是最佳布局的情况。
@PatriciaShanahan我怀疑这将"简单地"以任何语言实现,尤其是C ++
只是保持您的物体小。
@Patricia。好点子。但是Im出于其他原因(主要是可移植性,库,与现有应用程序的集成)而限制使用JVM。因此,我正在尝试在该限制内进行优化。同样,对于C ++,我也肯定Id仍在与语言作斗争,只是出于不同的原因(复杂对象图上的多线程GC?)
@HotLicks为什么将对象缩小?
@TheLQ Im不是说整个任务很简单。显然不是。我确实认为,无论程序员希望哪种方式,都可以强制将对象安排在内存中。
在这里看看。可惜该网站无法在平板电脑上运行(仍然使用Flash)。
@PatriciaShanahan-不太可能不必要地越过缓存行。
提高缓存行效率的第一步是提供参照位置(即,使数据彼此靠近)。在JAVA中很难做到这一点,在Java中几乎所有内容都是系统分配和通过引用来访问的。
为避免引用,以下内容可能很明显:
在您的字段中具有非引用类型(即int,char等)
对象
将对象保持在数组中
保持物体小
这些规则至少将确保在处理单个对象以及遍历对象图中的对象引用时具有一定的引用局部性。
另一种方法可能是根本不使用对象作为数据,而是为每个项目都具有全局非引用类型的数组(大小相同),该数组通常是您类中的一个字段,然后每个实例将由一个公共索引标识进入这些数组。
然后,为了优化阵列或其块的大小,您必须知道MMU特性(页面/缓存大小,缓存行数等)。我不知道JAVA是否在System或Runtime类中提供了此功能,但是您可以在启动时将此信息作为系统属性传递。
当然,这与您通常在JAVA中应该做的事情完全正交:)
最好的祝福
您可能需要有关CPU的各种缓存的信息,可以使用Cachesize(当前支持Intel CPU)从Java访问它。这可以帮助开发可识别缓存的算法。
免责声明:lib的作者。