我该如何处理Java中的一个非常大的数组?

Sim*_*mon 9 java nio

我有一个算法,它目前分配一个非常大的双精度数组,它经常更新和搜索.数组的大小为N ^ 2/2,其中N是算法运行的行数.为了与围绕算法的应用程序相关的目的,我还必须保留整个事物的副本.

当然,这限制了我的算法可以处理的行数,因为我有堆限制要与之抗衡.到目前为止,我已经离开了要求使用该算法的人更新-Xmx设置以分配更多空间,并且这已经正常工作.但是,我现在有一个真正的问题,我需要这个数组大于我可以适应内存.

我已经计划改变我的算法以减轻这个大型阵列的必要性,并在该领域有一些有希望的结果.然而,这是对该过程的根本改变,并且在它达到我当前代码的高度抛光条件之前需要更多的工作,该代码在生产中非常成功地运行并且已经存在了几年.

因此,当我完善我的新算法时,我想延长现有算法的寿命,这意味着解决与分配我庞大的双精度数组相关的堆限制.

我的问题是处理它的最佳方法是什么?我应该使用nio FileChannel和MappedByteBuffer,还是有更好的方法.如果我确实使用了nio方法,那么与相同大小的内存数组相比,我期望获得什么样的性能?

谢谢

Pau*_*and 6

如果你开始耗尽可用内存,那么你可能很快就会开始耗尽可用的数组索引,一个数组的大小限制为Integer.MAX_VALUE,并且当使用双精度数组元素时,"仅"32GB大小.

获得具有32GB内存的计算机是昂贵的,但可能没有您修改算法和所有相关测试的时间那么昂贵.

但是,如果客户端正在运行到内存边缘,并且它们的数据集仍在增长,那么现在咬你的子弹是有意义的,并使更改能够在任何给定时间使用更少的内存,因为它们无论如何,很可能会很快就会出现阵列.

假设数组有些稀疏填充,您拥有的另一个选项是使用各种稀疏数组结构中的一种,尽管如果您的数组小于20%,这些选项往往是有益的.

编辑:由于您似乎已经调查了替代方案,因此MappedByteBuffer可能就是您的选择.显然这会对性能产生影响,但是如果你主要从数组进行顺序读写操作,那么这应该不会太糟糕.如果你正在进行随机读写,那么这将非常快速地变慢.或者非常缓慢......取决于你如何看待这些东西;-)

  • 似乎更多内存回退的答案是"等到新算法完成".您是时候更好地花在研究新算法上还是护理旧算法?您是否有可用于说服客户的新算法的性能指标? (3认同)
  • +1用于突出显示硬件与开发成本 (2认同)

mar*_*inr 2

如果您在 PC 上运行,则映射文件的页面大小可能为 4 KB。

因此,问题实际上是从我开始将数据交换到磁盘开始的,“我对现在是文件的 RAM 的随机访问有多随机”?

并且(...我可以吗?如果可以...)我如何排序双精度数以最大化同时访问 4K 页面内的双精度数的情况,而不是在下一个 4K 磁盘获取之前在每个页面中一次访问几个双精度数?

如果您使用标准 IO,您可能仍然希望以块的形式进行读写,但块可能会更小。扇区至少为 512 字节,磁盘簇更大,但是考虑到每个 IO 都有内核往返开销,最好的读取大小是多少?

抱歉,但恐怕您接下来的最佳步骤在很大程度上取决于您正在使用的算法和数据。