优化Java对象以提高CPU缓存行效率 [英] Optimising Java objects for CPU cache line efficiency

查看:264
本文介绍了优化Java对象以提高CPU缓存行效率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个图书馆,其中:

  • 它将需要在各种不同的平台/Java实现上运行(常见的情况可能是在装有Windows或Linux的Intel 64位计算机上使用OpenJDK或Oracle Java)
  • 在我关心对象访问中CPU缓存行效率的范围内,高性能是重中之重
  • 在某些地区,将遍历/处理相当大的小物体图(假设约为1GB规模)
  • 主要工作量是几乎是独家阅读
  • 读取将分散在对象图中,但不会完全随机(即会有很大的热点,偶尔会读取访问频率较低的区域)
  • 多个线程将同时访问对象图(但不会对其进行修改).假设不会发生并发修改,则没有锁定.

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

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

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

解决方案

提高缓存行效率的第一步是提供参照位置(即,使数据彼此靠近).在JAVA中很难做到这一点,因为JAVA中几乎所有内容都是系统分配的,并通过引用进行访问.

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

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

在处理单个对象以及遍历对象图中的对象引用时,这些规则至少将确保某些参照位置.

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

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

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

最诚挚的问候

I'm writing a library where:

  • It will need to run on a wide range of different platforms / Java implementations (the common case is likely to be OpenJDK or Oracle Java on Intel 64 bit machines with Windows or Linux)
  • Achieving high performance is a priority, to the extent that I care about CPU cache line efficiency in object access
  • In some areas, quite large graphs of small objects will be traversed / processed (let's say around 1GB scale)
  • The main workload is almost exclusively reads
  • Reads will be scattered across the object graph, but not totally randomly (i.e. there will be significant hotspots, with occasional reads to less frequently accessed areas)
  • The object graph will be accessed concurrently (but not modified) by multiple threads. There is no locking, on the assumption that concurrent modification will not occur.

Are there some rules of thumb / guidelines for designing small objects so that they utilise CPU cache lines effectively in this kind of environment?

I'm particularly interested in sizing and structuring the objects correctly, so that e.g. the most commonly accessed fields fit in the first cache line etc.

Note: I am fully aware that this is implementation dependent, that I will need to benchmark, and of the general risks of premature optimization. No need to waste any further bandwidth pointing this out. :-)

解决方案

A first step towards cache line efficiency is to provide for referential locality (i.e. keeping your data close to each other). This is hard to do in JAVA where almost everything is system allocated and accessed by reference.

To avoid references, the following might be obvious:

  1. have non-reference types (i.e. int, char, etc.) as fields in your objects
  2. keep your objects in arrays
  3. keep your objects small

These rules will at least ensure some referential locality when working on a single object and when traversing the object references in your object graph.

Another approach might be to not use object for your data at all, but have global non-ref typed arrays (of same size) for each item that would normally be a field in your class and then each instance would be identified by a common index into these arrays.

Then for optimizing the size of the arrays or chunks thereof, you have to know the MMU characteristics (page/cache size, number of cache lines, etc). I don't know if JAVA provides this in the System or Runtime classes, but you could pass this information as system properties on start up.

Of course this is totally orthogonal to what you should normally be doing in JAVA :)

Best regards

这篇关于优化Java对象以提高CPU缓存行效率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆