3

在 Java 中为多个(数百万)小对象(包含 3 到 6 个双精度对象,可能是字符串)分配内存的最佳方法是什么(最少的内存消耗/交换)?

我可以想到三种不同的策略:

  1. 天真:什么都不做,让虚拟机处理内存。

  2. 工厂风格:通过工厂类创建对象。工厂一次创建多个对象(每批大约数千个)并处理对象回收(如果有使用的对象,则无需创建新对象)。

  3. 数组样式:将数据存储在基本数组中。通过索引号访问数据。

澄清: 目标平台的内存非常低(512 兆字节)。

4

3 回答 3

1

选项 1。当然。几百万个对象没什么特别的,VM 可以轻松管理它。

选项 2 可能不会对内存使用产生影响,而数字 3 是可用的最差选项。请参阅 Effective Java,第 2 版中的第 55 项。

于 2013-07-16T12:54:39.790 回答
1

选项 3 当然是最有效的记忆。

例子:

class Point {
  double x;
  double y;
}

Point 对象需要 12,x 和 y 需要 2 * 8 = 28 个字节
Point[]:使用 Point 对象数组:每个点 28 个字节(数组本身需要 16 个字节)

现在为
int[] xycoords: order: x1,y1,x2,y2,.....xn,yn:

每个 x,y 坐标需要 16 个字节。与类点相比,这是 57%

想象一下,您已经构建了导航系统,并且由于次优数据表示,您只能存储一半的欧洲。

但是
虽然选项 3 可以节省内存,但我建议对第一个版本使用 obejct 方法。数组方法有更多的编码错误概率,特别是对于复杂的算法。

一旦版本 1 工作(并且希望您有单元测试),您可以使用数组方法实现 v2。并检查您的单元测试是否仍然有效。

于 2013-07-16T13:24:48.453 回答
1

假设最坏的情况(6 双),一切都应该适合内存。

解释:你说双而不是双。如果我记得正确的话,包装器开销是 16 个字节。这意味着 16(包装器开销)+ 8(双精度值)= 每个 Double 24 字节。6 双倍 200 万 : ~ 274 Mo

结果:选择选项 1。

如果想要一些优化提示:

  • 选择双而不是双。
  • 由于开销而不使用基本数组,请尝试使用 Java 中的 BitSet 或更好(我认为开销更低)的库,如 Colt 及其BitVector。这有助于在不牺牲性能的情况下优化空间。
  • 尝试您想到的任何东西,但要对其进行基准测试。如果它不能按预期工作,您将从经验中学习!
于 2013-07-16T14:02:32.103 回答