2

私は Javascript のクロージャについて多くのことを読んできました。私はより伝統的な (C、C++ など) 背景から来て、コール スタックなどを理解していますが、Javascript でのメモリ使用量に問題があります。私が設定した(簡略化された)テストケースは次のとおりです。

function updateLater(){
    console.log('timer update');

    var params = new Object();
    for(var y=0; y<1000000; y++){
        params[y] = {'test':y};
    }
}

または、クロージャーを使用してみました:

function updateLaterClosure(){

return (function(){

    console.log('timer update');
    var params = new Object()
    for(var y=0; y<1000000; y++)
    {
        params[y] = {'test':y};
    }
});
}

次に、関数を実行する間隔を設定します...

setInterval(updateLater, 5000); // or var c = updateLaterClosure(); setInterval(c,5000);

タイマーが初めて実行されると、メモリ使用量が 50MB から 75MB に跳ね上がります (Chrome のタスク マネージャーによる)。2 回目は 100MB を超えます。時折、少し下がることがありますが、75MB を下回ることはありません。

自分でチェックしてください: https://local.phazm.com:4435/Streamified/extension/branches/lib/test.html

明らかに、最初のタイマー呼び出しからのメモリが解放されていないため、params は完全にガベージ コレクションされていません...まだ、各呼び出しで 25MB のメモリを追加していないため、ガベージ コレクションが決して発生していないわけではありません...「params」の 1 つのインスタンスが常に保持されているように見えます。サブクロージャーなどを設定しようとしました...サイコロはありません。

ただし、最も気がかりなのは、メモリ使用量が増加傾向にあることです。今のところ「ちょうど」75MB かもしれませんが、十分に長く (一晩) 実行しておくと、500 MB になります。

アイデア?

ありがとう!

4

2 に答える 2

1

それも閉鎖ではありません。クロージャとは、配列、関数、オブジェクト、または参照を含むことができるものなど、関数から何かを返すことであり、その関数のすべてのローカルメンバーを運びます。

あなたが持っているのは、非常に大きなオブジェクトを構築している非常に長いループの場合です。そして多分あなたの記憶はあなたが巨大なオブジェクトを構築しているほど速く回収されないでしょう。

于 2012-04-20T23:27:06.233 に答える
1

25MB を割り当てると、GC が発生します。この GC は最後のインスタンスをクリーンアップしますが、もちろん現在のものはクリーンアップしません。したがって、常に 1 つのインスタンスが存在します。

プログラムがアイドル状態の場合、GC は発生しません。タイマー呼び出しの間には発生しないため、メモリは残ります。

于 2012-04-20T23:21:12.570 に答える