在V8中,为什么预分配的阵列会消耗更少的内存?

时间:2017-02-22 22:38:33

标签: javascript arrays memory v8

考虑以下两种选择:

  const mb_before = process.memoryUsage().heapUsed / 1024 / 1024;
  const n = 15849;
  const o = 115;
  const entries = [];
  for (var i = 0; i < n; i++) {
    const subarr = [];
    for (var j = 0; j < o; j++) {
      subarr.push(Math.random());
    }
    entries.push(subarr);
  }
  const mb_after = process.memoryUsage().heapUsed / 1024 / 1024;
  console.log('arr using ' + (mb_after - mb_before) + ' megabyte');
  // arr using 15.110992431640625 megabyte

  const mb_before = process.memoryUsage().heapUsed / 1024 / 1024;
  const n = 15849;
  const o = 115;
  const entries = new Array(n);
  for (var i = 0; i < n; i++) {
    const subarr = new Array(o);
    for (var j = 0; j < o; j++) {
      subarr[j] = Math.random();
    }
    entries[i] = subarr;
  }
  const mb_after = process.memoryUsage().heapUsed / 1024 / 1024;
  console.log('arr using ' + (mb_after - mb_before) + ' megabyte');
  // arr using 12.118911743164062 megabyte

从我的理解两个阵列&#39;大小应该相同,只是它们实例化的方式不同。如何解释所产生的内存使用量始终不同?

2 个答案:

答案 0 :(得分:2)

我认为这与分配数组内存的方式有关。当你实例化一个数组,给它一个特定的大小,就像你在第二个例子中一样,它会分配那个内存。

当你增长数组时,它将分配少量额外空间来处理增长,然后随着数组的增长,额外的内存分配将变得更大。这会在第一个示例中产生额外的可用空间。

答案 1 :(得分:1)

我觉得这一点都不令人惊讶。虽然标准数组aren't really arrays at all *,但JavaScript引擎默认为优化:尽可能将它们作为数组进行处理。

在你的第一个例子中,V8不知道每个数组的大小 - 它只是不断增长,并且为了将其视为优化数组(而不是具有特殊属性的对象),V8必须保持重新分配和复制,以使其定期更大。因此,最新的主动分配在不断增长的情况下留下了大量额外空间也就不足为奇了。

在你的第二个例子中,你已经为V8提供了一个很大的线索,提前知道你打算制作数组的大小。因此,V8将使用该信息来优化它对底层真实阵列的分配是合理的。

* (这是我贫血的小博客上的帖子)