如果您要处理的数据主要或全部由原语组成(例如,在数字问题中),我建议您采取以下措施。
在初始化时分配固定大小的原始数组的平面结构,并确保其中的数据被定期压缩/整理(0-> n,其中n是给定元素数量的最小最大索引),以进行迭代 使用for循环。 这是保证Java中连续分配的唯一方法,而压缩进一步有助于提高引用的局部性。 压缩是有益的,因为它减少了对未使用元素进行迭代的需要,减少了条件数:随着for循环迭代,终止发生得更早,并且更少的迭代=通过堆的移动更少=缺少高速缓存丢失的机会。 尽管压缩本身会产生开销,但如果您选择这样做,则只能定期执行(相对于您的主要处理领域)。
更好的是,您可以在这些预分配的数组中交织值。 例如,如果您要表示2D空间中成千上万个实体的空间变换,并且正在为每个这样的实体处理运动方程,则可能会出现紧密的循环,例如
int axIdx, ayIdx, vxIdx, vyIdx, xIdx, yIdx;
//Acceleration, velocity, and displacement for each
//of x and y totals 6 elements per entity.
for (axIdx = 0; axIdx < array.length; axIdx += 6)
{
ayIdx = axIdx+1;
vxIdx = axIdx+2;
vyIdx = axIdx+3;
xIdx = axIdx+4;
yIdx = axIdx+5;
//velocity1 = velocity0 + acceleration
array[vxIdx] += array[axIdx];
array[vyIdx] += array[ayIdx];
//displacement1 = displacement0 + velocity
array[xIdx] += array[vxIdx];
array[yIdx] += array[vxIdx];
}
此示例忽略了诸如使用其关联的(x,y)渲染这些实体之类的问题...渲染始终需要非基本体(因此,引用/指针)。 如果确实需要此类对象实例,则无法再保证引用的局部性,并且可能会遍及整个堆。 因此,如果您可以将代码分成如上所示进行原始密集型处理的部分,那么这种方法将对您有很大帮助。 至少对于游戏而言,人工智能,动态地形和物理可能是处理器最密集的方面,并且都是数字的,因此这种方法可能非常有益。