在Java中分配大量相对较小的对象

时间:2013-07-16 12:53:26

标签: java memory-management

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

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

  1. 天真:不要做任何特别的事情,让虚拟机处理内存。

  2. 工厂风格:通过工厂类创建对象。工厂创造 一次多个对象(每批数千个)和句柄 对象回收(如果有可用的则不需要创建新对象)。

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

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

3 个答案:

答案 0 :(得分:1)

选项1.当然。几百万个对象并不特别,VM可以轻松管理它。

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

答案 1 :(得分:1)

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

示例:

class Point {
  double x;
  double y;
}

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

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

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

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

<强>但是
虽然选项3节省了内存,但我建议在第一个版本中使用obejct方法。阵列方法具有更高的编码错误概率,尤其是 对于复杂的算法。

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

答案 2 :(得分:0)

假设最坏情况(6 Double),一切都应该适合记忆。

<强>解释: 你说双倍而不是双倍。如果我记得correclty,包装器开销是16个字节。 这意味着16(包装器开销)+ 8(双值)=每个Double 24个字节。 6倍双倍2百万:~274 Mo

后果:转到选项1。

如果想要一些优化提示:

  • 选择双倍而不是双倍。
  • 不用基本的 由于开销导致的数组,尝试使用Java或更好的BitSet(更低 我认为)像柯尔特这样的库BitVector。这个 可以帮助优化空间,而不会牺牲性能。
  • 尝试你想到的任何东西,但要对它进行基准测试。如果它不起作用 正如预期的那样,您将从经验中学习!