jsにおけるごみ回収メカニズム

3124 ワード

jsには自動ゴミ回収メカニズムがあり、すなわち、実行環境はコード実行中に使用されるメモリの管理を担当する.CやC++などの言語では、開発者の基本的なタスクの一つは、メモリの使用状況を手動で追跡することであり、多くの問題の根源となっています.jsプログラムを作成する際,開発者はメモリの使用問題に関心を持たず,必要なメモリの割り当てや不要なメモリの回収を完全に自動管理した.このごみ回収メカニズムの原理は、使用を継続しない変数を見つけて、使用するメモリを解放することです.このため、ゴミ回収器は、一定の時間間隔(またはコード実行中に所定の回収時間)で周期的に実行される.
関数のローカル変数のライフサイクル:ローカル変数は、関数の実行中にのみ存在します.このプロセスでは、ローカル変数にスタック(またはスタック)メモリに対応するスペースが割り当てられ、値が格納されます.次に、関数の実行が終了するまで、関数でこれらの変数を使用します.この場合、ローカル変数は必要ありませんので、将来使用するためにメモリを解放できます.この場合、変数がまだ存在する必要があるかどうかを判断しやすい.しかし、すべての状況でこのように簡単に結論を出すわけではない.ごみ回収器は、どの変数が役に立つか、どの変数が役に立たないかを追跡し、将来使用したメモリを回収するために、もう役に立たない変数にマークを付ける必要があります.不要な変数を識別するためのポリシーは、インプリメンテーションによって異なる場合がありますが、ブラウザのインプリメンテーションには通常2つのポリシーがあります.
タグクリアjsで最もよく使われるゴミ回収方式はタグクリアです.変数が環境に入ると、たとえば関数に変数を宣言すると、この変数を「環境に入る」とマークします.論理的には、ストリームが対応する環境に入ると使用される可能性があるため、環境に入る変数に使用されるメモリは解放されません.変数が環境から離れると、「環境から離れる」とマークされます.任意の方法で変数をマークできます.たとえば、特定のビットを反転して、変数が環境に入るタイミングを記録するか、「環境に入る」変数リストと「環境から離れる」変数リストを使用して、どの変数が変化したかを追跡できます.結局、変数をどのようにマークするかは重要ではありません.肝心なのは、どのような戦略を取るかです.ゴミ回収器は、実行時にメモリに格納されているすべての変数にタグを付けます(もちろん、任意のタグ方式を使用できます).その後、環境内の変数と、環境内の変数によって参照される変数のタグが削除されます.その後、タグ付けされた変数は、環境内の変数がこれらの変数にアクセスできないため、削除の準備をしている変数と見なされます.最後に、ゴミ回収器はメモリの消去を完了し、タグ付きの値を破棄し、使用したメモリ領域を回収します.
2008年までIE、Firefox、Opera、Chrome、Safariのjs実装で使用されていたのは、パージ業者のゴミ回収ポリシーや類似のポリシーであったが、ゴミ収集の時間間隔は互いに異なる.
参照カウント参照カウントとは、各値が参照された回数を追跡することを意味する.変数を宣言し、参照タイプの値を変数に割り当てると、この値の参照回数は1になります.同じ値が別の変数に割り当てられている場合、その値の参照回数には1が加算されます.逆に、この値を参照する変数を含めて別の値を取得した場合、この値の参照回数は1減少する.この値の参照回数が0になると、この値にアクセスできないため、使用したメモリ領域を回収できます.これにより、ゴミ回収器が次回再実行されると、参照回数0の値が消費されるメモリが解放されます.Netscape Navigator 3は、参照カウントポリシーを最初に使用したブラウザですが、すぐに循環参照という深刻な問題に直面します.循環参照とは、オブジェクトAにオブジェクトBを指すポインタが含まれ、オブジェクトBにもオブジェクトAを指す参照が含まれていることを意味する.
function problem(){
	var objA=new Object();
	var objB=new Object();

	objA.b=objB;
	objB.a=objA;
}

この例では、objAとobjBはそれぞれの属性によって相互に参照される.すなわち,この2つのオブジェクトの参照回数はいずれも2である.タグクリアポリシーの実装では、関数の実行後、両方のオブジェクトが役割ドメインから離れているため、この相互参照は問題ありません.しかし、参照カウントポリシーの実装では、関数の実行が完了すると、objAおよびobjBは、参照回数が0ではないため、引き続き存在します.この関数が複数回呼び出されると、大量のメモリが回収されません.このためNetscapeはNavigator 4において参照カウント方式を放棄し,タグクリアを用いてそのゴミ回収機構を実現する.しかし、引用カウントによるトラブルは終わらなかった.
IEの一部のオブジェクトが生jsオブジェクトではないことを知っている.例えば、DOMとBOMのオブジェクトはC++を使用してCOMオブジェクトとして実現され、COMオブジェクトのゴミ回収メカニズムは参照カウントポリシーを採用している.したがって、IEのjsエンジンがタグクリアポリシーを用いて実装されても、jsがアクセスするCOMオブジェクトは参照カウントポリシーに基づいている.言い換えれば、IEにCOMオブジェクトが含まれている限り、ループリファレンスの問題がある.
var element=document.getElementById("some_element");
var myObject=new Object();
myObject.e=element;
element.o=myObject;

この例はDOM要素(element)と原生jsオブジェクトである.(myObject)間で循環参照が作成されます.変数myObjectにはelementという属性がelementオブジェクトを指します.変数elementにはoリターンmyObjectという属性もあります.この循環参照が存在するため、例のDOMがページから削除されても回収されません.
このようなループリファレンスの問題を回避するには、それらを使用しないときに、元のjsオブジェクトとDOM要素との接続を手動で切断することが望ましい.たとえば、前の例で作成したループリファレンスを次のコードで除去することができます.
myObject.element=null;
element.o=null;

変数をnullに設定すると、変数と以前参照していた値との接続が切断されます.ゴミ回収器が次回実行されると、これらの値が削除され、使用したメモリが回収されます.
良い文章の推薦:
『JavaScriptメモリの漏洩を解決する』https://boke.io/gao-ding-nei-cun-xie-lou/