Node.js 中稀疏数组的内存消耗

Memory consumption of sparse arrays in Node.js

我写了一个生成数组的小程序,运行相当长(几乎永远 ;-)):

var results = [];
var i = 1;

while (true) {
  console.log(i++);
  results.push([]);
}

当我创建长度为 i 的稀疏数组而不是空数组时,程序崩溃得非常快:

var results = [];
var i = 1;

while (true) {
  console.log(i);
  results.push(new Array(i++));
}

实际上我达到 i 等于 17424,然后我收到一条错误消息告诉我

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Abort trap: 6

和 Node.js 将我带回控制台。由于唯一的区别是第二个生成 "larger" 个空数组而不是第一个,这意味着长度为 n 的空稀疏数组占用 n 乘以 space长度为 1.

的空数组

我对此是否正确(特别是 Node.js)?

还有一个问题:如果我运行

var results = [];
var i = 1;

while (true) {
  console.log(i);
  var temp = [];
  temp[i++] = i;
  results.push(temp);
}

然后我达到 1286175,然后它再次崩溃:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Abort trap: 6

为什么这与其他两个选项的行为不同?

PS:我在 OS X 上使用 Node.js 0.12.0 到 运行。

当你声明一个大小为

的数组时
Array(1024);

你这样做是为了它为 1024 个元素分配 space。它必须预先分配这个space,因为这种声明数组的形式是一种优化声明

"I need you to reserve 1024 locations so that you aren't constantly resizing the array as I push more elements onto it".

正如您可能知道的那样,用简单的 [] 声明一个数组仍然允许您将无限数量的元素压入其中,但是该数组正在悄悄地调整大小(很可能是 memcpy())允许这种行为的场景。

编辑:

您在第二个示例中获得更高迭代次数的原因是您现在使用的是稀疏数组。用稀疏数组做

var arr = []
arr[1000000] = 1;

并不意味着您的数组现在正在使用内存中的 1,000,000 个条目。将此与密集数组进行对比

var arr = Array(1000000);

它明确告诉运行时保留一个可以在内存中存储 1000000 个条目的数组。

相关 Whosebug 问题:

Node 中的 JS 引擎 V8 在看似空的数组中为每个元素使用 4 个字节。确定这一点的最佳方法是在 Chrome 中创建空数组并使用探查器查看数组已经用完了多少额外大小。有关如何执行此操作的详细信息,请参阅 https://developer.chrome.com/devtools/docs/heap-profiling...