7

配列を生成する小さなプログラムを作成しましたが、これは非常に長く実行されます (ほぼ永久に ;-)):

var results = [];
var i = 1;

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

空の配列の代わりに length のスパース配列を作成するiと、プログラムが非常に速くクラッシュします。

var results = [];
var i = 1;

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

実際にはi17424 に等しくなり、エラー メッセージが表示されます。

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

Node.js によってコンソールに戻ります。唯一の違いは、2 番目のものは最初のものよりも「大きい」空の配列を生成することであるため、これは、長さの空のスパース配列が lengthの空の配列のスペースの倍nを占めることを意味します。n1

私はこれについて正しいですか (特に Node.js に対して)?

もう 1 つの質問: 実行した場合

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

これが他の 2 つのオプションと異なる動作をするのはなぜですか?

PS: Node.js 0.12.0 を使用して、これを OS X で実行しています。

4

2 に答える 2

10

サイズを指定して配列を宣言する場合

Array(1024);

1024 個の要素にスペースを割り当てるようにしています。この形式の配列宣言は最適化状態であるため、このスペースを前もって割り当てる必要があります。

「より多くの要素を配列にプッシュするときに配列のサイズを常に変更しないように、1024 の場所を予約する必要があります」.

おそらくご存じのとおり、 で配列を宣言すると、無制限の数の要素を配列にプッシュできますが、配列はこの動作を可能にするために舞台裏[]で静かにサイズ変更されています (おそらく)。memcpy()

編集:

2 番目の例で反復回数がはるかに多い理由は、スパース配列を使用しているためです。まばらな配列で

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

配列がメモリ内の 1,000,000 エントリを使用しているという意味ではありません。これを密な配列と比較してください

var arr = Array(1000000);

これは、メモリに 1000000 エントリを格納できる配列を予約するようランタイムに明示的に指示します。

関連する StackOverflow の質問: https://stackoverflow.com/a/1510842/276949

于 2015-04-23T06:08:42.917 に答える
6

Node の JS エンジンである V8 は、一見空の配列の各要素に 4 バイトを使用します。これを確認する最善の方法は、Chrome で空の配列を作成し、プロファイラーを使用して、配列がどれだけの追加サイズを使用したかを確認することです。これを行う方法の詳細については、 https://developer.chrome.com/devtools/docs/heap-profilingを参照してください...

于 2015-04-23T06:18:12.017 に答える