ホームページ >ウェブフロントエンド >jsチュートリアル >JSメモリ管理の例の説明
JS には完全なメモリ処理メカニズムがあるため、以前はこれの実装に特別な注意を払う必要はありませんでした。ページが高速でない場合は、更新するだけで問題ありません。ブラウザが停止している場合は、再起動すれば問題ありません。ただし、SPA とモバイル APP の人気、および将来的には PWA が実装される可能性があるため、JS メモリが新たなメモリ ボトルネックになる可能性があります。
エンコーディングが間違っているために、一部のメモリを使用しないことにした場合、GC (ガベッジ コレクション) がこれらのメモリを正しくリサイクルできなくなり、これがメモリ リークです。
オブジェクトによって占有されるメモリは、直接占有メモリ (浅いサイズ) と総占有メモリ (保持サイズ) に分けられます。 ))。
メモリを直接占有 : オブジェクト自体が占有するメモリ。一般的な JavaScript オブジェクトには、オブジェクトを記述し、その直接値を保存するために使用される予約メモリがあります。一般に、直接メモリを大幅に占有するのは配列と文字列だけです (浅いサイズ)。ただし、文字列と配列は多くの場合、メイン データ部分をレンダラー メモリに保存し、JavaScript オブジェクト スタック内の小さなラッパー オブジェクトのみを公開します。
総占有メモリ: 直接占有されているメモリと、この参照によって参照される依存オブジェクトによって占有されているメモリ。
代入と新規操作にはメモリが使用されます。
Chrome V8 のガベージ コレクション (GC) アルゴリズムは世代別コレクションに基づいており、メモリはヤング ジェネレーション (YG) とオールド ジェネレーション (OG) と呼ばれる 2 つのタイプに分けられます。
いわゆる若者と老人は、占める時間に応じて分けられます。 YG ではメモリの割り当てとリサイクルが高速で頻繁であり、一般に短時間しか存在しないため、ヤングと呼ばれます。一方、OG では、メモリの割り当てと再利用が遅く、めったに発生しないため、オールドと呼ばれます。
V8 では、YG の GC プロセスはプログラムをブロックしますが、OG の GC はブロックしません。そのため、通常、開発者は YG の詳細に関心を持ちます。
YG は、それぞれ From と To と呼ばれる空間の 2 つの部分に分割されます。すべてのメモリは To 空間から割り当てられます。To がいっぱいになると GC が開始されます。詳しく見てみましょう。
ある時点で、To は A、B、C にメモリを割り当てました。現在、割り当てられていない小さなメモリが残っており、From のメモリはすべて空き状態です。
このとき、プログラムはDにメモリを割り当てる必要がありますが、以下に示すようにDが必要とするメモリサイズがToの未割り当てメモリを超えています。この時点で、GC がトリガーされ、ページの実行が停止します。
その後、From と To が交換されます。つまり、元の To スペースは From としてマークされ、From は To としてマークされます。そして、ライブ変数の値 (B など) がマークされ、「ガベージ」 (AC など) がマークされていない場合、それらはクリアされます。
ライブBがTo空間にコピーされ、「ゴミ」ACがリサイクルされ、同時にDがTo空間に割り当てられ、最終的には以下のように配置されます。
それだけです。GC 全体が完了し、このプロセス中にページの実行が停止するため、できるだけ高速にする必要があります。 YG の値が長期間存続すると、OG にプッシュされ、OG のスペースがいっぱいになると、OG の GC が YG の GC をトリガーします。
各割り当てにより To の利用可能なスペースが減り、プログラムは GC に近づきます
YG の GC はプログラムをブロックするため、GC 時間は 10 ミリ秒以内で長すぎないようにしてください。 16ms ではフレーム損失が発生します。GC は頻繁に行わないでください。特定の値がゴミになった後、メモリはすぐに解放されず、GC 中に占有されていたメモリのみがリサイクルされます。
2.2 内容はすべて参考資料からです
2.3 メモリのリサイクル
GC ルートはブラウザではウィンドウ、NodeJSではメモリのルートノードです。グローバルなオブジェクト。
GC ルートから開始してグラフをたどります。到達可能なすべてのノードはライブ ノードと呼ばれます。GC ルートによって到達できないノードがある場合、そのノードは「ガベージ」と呼ばれます。図の灰色のノードに示すように、リサイクルされます。
ルートノードのリサイクルに関しては、ユーザーの制御下にはありません。
ルートノードへのパスが完全に切断されていないため、自動GCはこれをリサイクルしません一部のメモリが不足し、メモリ リークが発生します。
具体的な理由は次のとおりです:
オブジェクト間の相互参照
<span style="font-size: 14px;">var a, b;<br>a.reference = b;<br>b.reference = a;<br></span>
グローバル変数の不正な使用
<span style="font-size: 14px;">a = "1234567";<br>相当于<br>window.a = "1234567";<br></span>
DOM 要素がクリアまたは削除されると、バインドされたイベントはクリアされません
<span style="font-size: 14px;"><p id="myp"><br> <input type="button" value="Click me" id="myBtn"><br></p><br><br><script type="text/javascript"><br> var btn = document.getElementById('myBtn');<br> btn.onclick = function () {<br> document.getElementById('myp').innerHTML = 'Processing...';<br> /* 清除事件绑定 */<br> // btn.onclick = null;<br> };<br></script><br></span>
クロージャ参照
<span style="font-size: 14px;">function bindEvent() {<br> var obj = document.getElementById('xxx');<br><br> obj.onclick = function () {<br> /** 空函数*/<br> };<br><br> /** delete this reference */<br> // obj = null;<br>}<br></span>
DOM要素がクリアまたは削除されると、子要素にJS参照が存在し、すべての親要素が子要素は削除されます
<span style="font-size: 14px;">// b是a的子dom节点, a是body的子节点<br>var aElement = document.getElementById("a");<br>var bElement = document.getElementById("b");<br>document.body.removeChild(aElement);<br>// aElement = null;<br>// bElement = null;<br></span>
は、次のようなnodejsでより多く発生します:
制御不能ループ
<span style="font-size: 14px;">while(1) {<br> // do sth<br>}<br></span>
合格しました大規模な配列
<span style="font-size: 14px;">var arr = [];<br>for (var i=0; i< 100000000000; i++) {<br> var a = {<br> 'desc': 'an object'<br> }<br> arr.push(a);<br>}<br></span>関連する推奨事項:
以上がJSメモリ管理の例の説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。