1.メモリリークとメモリオーバーフロー
-
メモリ リーク (メモリ リーク):使用されなくなったメモリは時間内に解放されません。
-
メモリ不足:再利用できないメモリがあるか、アプリケーション システムで使用されているメモリが多すぎます。これにより、実行中のプログラムが使用するメモリが、提供できる最大メモリよりも大きくなります。
2.漏れの理由
-
js
メソッドの書き込み (クロージャ、グローバル変数など)、dom
イベント監視、サイクル タイマーなどによるリーク。 -
コンポーネントのリーク (
DOM
リークとは、コンポーネントDOM
を破棄できないことを意味します) は、DOM
アップロードされたイベントやオブジェクト配列などのデータを解放できなくなります。
3.chrome Memory
はじめに
コンソールのパネルを開くMemory
か、長押ししてF12
開きます。
ヒープ スナップショットの種類を選択します。私は通常、最初の 2 つを使用します:Heap snapshot(JS堆快照)
とAllocation instrumentation on timeline(JS堆分配时间线)
.
記録を開始する前に、[ガベージ コレクション] をクリックし、[記録の開始] をクリックします。ヒープ メモリがタイムラインに動的に割り当てられている場合はJS
、記録が終了する前にガベージ コレクションをもう一度クリックしてから、記録を終了します。
4. ソリューション
4.1、JS ヒープのスナップショット
Summary
概要ビュー:コンストラクターごとにグループ化。オブジェクトとそれらが使用するメモリをキャプチャするために使用されます。DOM のメモリ リークを特定するのに特に役立ちます。
Comparison
比較ビュー: 2 つのスナップショットを比較します。さまざまな操作後のヒープ スナップショットを比較し、メモリの解放と参照カウントを確認し、メモリ リークが発生しているかどうかとその原因を分析するために使用されます。
Containment
コンテンツ ビュー:ヒープの内容を表示します。オブジェクト構造を表示するのに適し、オブジェクトの参照状況を分析するのに役立ちます。クロージャーの分析やオブジェクトの詳細な分析に役立ちます。
Statistics
統計ビュー:ヒープ統計の概要。
Summary
概要図
説明:
Constructor:
ノードの下のコンストラクターとオブジェクトはすべて、コンストラクターを変更することによって作成されます。
Distance:
ルート ノードからの距離。
Objects Count:
オブジェクトの数とパーセンテージ。
Shallow size:
オブジェクトの直接メモリーの合計量。直接メモリーとは、オブジェクト自体が占有するメモリー・サイズを指します。
Retained size:
オブジェクトの最大予約メモリ。予約メモリとは、オブジェクトの削除後に解放できるメモリの部分を指します。
Click to expand the constructor, and you can see all object instances related to the constructor. @ の後の数字は、オブジェクト インスタンスの一意の識別子です。
一般的な最上位コンストラクター:
(global property):
グローバルオブジェクトと通常オブジェクトの中間オブジェクトは、従来の考え方とは異なります。たとえば、Person オブジェクトが Window で定義されている場合、それらの間の関係は です[global] => (global property) => Person
。中間オブジェクトを使用する理由は、パフォーマンスを考慮するためです。(closure):
関数クロージャーを使用するオブジェクト。(array, string, number, regexp):
プロパティが指すオブジェクト型の配列Array/String/Number/Regexp。
HTMLDivElement/HTMLAnchorElement/DocumentFragment:
コードによって参照される要素または特定のドキュメント オブジェクトへの参照。
黄色のオブジェクト インスタンスは、JS コードによって参照されることを意味し、赤色のオブジェクト インスタンスは、黄色のノードによって参照されるフリー ノードを意味することに注意してください。新しいバージョン (テスト済み 69) にはカラー コードがないようです。
JS ヒープ スナップショットを使用して、DOM リークを見つけることができます。クラス フィルター (クラス フィルター) テキスト ボックスに Detached と入力して、デタッチされた DOM ツリーを検索します。分離されたノードが JS によって参照されている場合は、リーク ポイントである可能性があります。例として、次のコードを取り上げます。
<html>
<head>
</head>
<body>
<button id="createBtn">增加节点</button>
<script>
function create() {
var ul = document.createElement('ul');
for (var i = 0; i < 10; i++) {
var li = document.createElement('li');
ul.appendChild(li);
}
detachedNodes = ul;
}
document.getElementById('createBtn').addEventListener('click', create);
</script>
</body>
</html>
スナップショットをクリックする前にガベージ コレクションをクリックします。
[ノードの追加] ボタンを 1 回クリックすると、記録スナップショットは次のようになります。
参照されている < ul > 分離ノードがあることがわかりましたwindow.detachedNodes
。コードを見ると、var 宣言がないため、グローバル変数になっています。したがって、DOM を解放することはできません。
Comparasion
比較ビュー
特定の操作がメモリ リークを引き起こすかどうかを確認するために、スナップショットを比較する手順は次のとおりです。 1. 何も操作せず、
最初のヒープ スナップショットを取得
します。操作
3. 2 番目のヒープ スナップショットを取得し、比較ビューに切り替えて、最初のヒープ スナップショットとの比較を指定します
たとえば、ログイン ページのメモリがリークしていると感じた場合は、最初にホームページにログインして、最初のヒープ スナップショットを取得できます。次に、ログイン インターフェイスを終了し、再度ホームページにログインして、2 番目のスナップショットを記録します。2 つのスナップショットのサイズを比較する、成長が漏れの可能性がある場合は、操作を数回繰り返すことができます。各録音の前にクリックすることを忘れないでくださいガベージ コレクション。
比較を使用して、最初と 2 番目のスナップショットの違いを確認します
知らせ:
Chrome
開発者ツールで関数を確認Memory
すると、各コンポーネントでメモリリークが発生して起動できなくなっている原因がわかります.
このときは、消去法を使用してリークポイントを見つける必要があります.メインメニューの切り替え時にメモリリークが発生する.まず,各メニューページの内容にフルアノテーションを付けてから,メインメニューを切り替える.テストの結果,メモリリークは発生していません.
Containment view
スナップショットコンテンツ ビューの表示
コンテンツ ビューは、実際にはアプリケーションのオブジェクト構造の鳥瞰図です。これにより、関数クロージャーにドリルダウンし、VM 内部オブジェクトを観察し、アプリケーションの基礎となるメモリ使用量を確認できます。
このビューには、いくつかの一般的なエントリが表示されます。
DOMWindow objects
:JavaScript
コードのグローバル オブジェクトNative objects:
ブラウザーのネイティブ オブジェクトは、DOM
ノードやCSS
ルールなどの簡単な操作のために JS 仮想マシンに統合されます。
クロージャーに関する小さな提案: 名前付き関数のクロージャーは、無名関数のクロージャーよりも分析とデバッグが容易です。
// 匿名闭包
function createLargeClosure() {
var largeStr = new Array(1000000).join('x');
var lC = function() {
return largeStr;
};
return lC;
}
// 命名闭包
function createLargeClosure() {
var largeStr = new Array(1000000).join('x');
var lC = function lC() {
return largeStr;
};
return lC;
}
スナップショット統計の統計ビューを表示する
スタック統計の概要。ヒープ スナップショットの分布を明確に確認できます。
4.2、JS ヒープ割り当てタイムライン
ヒープ割り当てを継続的に記録することでAllocation instrumentation on timeline
、オブジェクトが作成されたとき、メモリ リークが発生したときなどを示します。
上のバーは、ヒープに作成された新しいオブジェクトを表します。高さはオブジェクトのサイズを示し、色はオブジェクトのメモリ リリースを示します。青色の列は、オブジェクトがtimeline
で生成され、終了前にまだ存在していることを示します。灰色の列は、オブジェクトがtimeline
で生成されたが、終了前にリサイクルされています。
アクションを繰り返し実行できますが、最後に保持される青色の列が多数ある場合、これらの青色の列はメモリ リークの可能性があります。
左側に予期しない青いバーがある場合は、メモリ リークの可能性が高いです。
上記は、Vue
2 つの記録間で繰り返し切り替えられるプロジェクトのヒープ割り当て動作です. 特定のヒープ割り当てに焦点を当て、特定のオブジェクト情報を表示できます. ヒストグラムでマウス ホイールをスライドすると、一定期間のヒープ割り当てを表示できます。たとえば、そのうちの 3 つはVueComponent
リサイクルされていないことがわかりました。クリックして拡大すると詳細が表示されます。これら 3 つのコンポーネントの情報は同じであることがわかります。つまり、コンポーネントはリリースされていません。まず、コンポーネントが破壊されているかどうかを確認します。破棄されている場合は、イベントがアンバインドされ、タイマーがキャンセルされているかどうかを確認します.イベントバスにバインドされたイベントのアンバインドには特に注意してください. オブジェクト、データ、イベントがマウントされるため、値のリークも発生する可能性があるため、値のリークに
注意してください。したがって、リークに対処するときは、最初にリーク値が 0 であることを確認し、次に js クロージャ、ループ タイマー、およびイベント リスナーに移動して確認するのが最善です。VueComponent
VueComponent
Object Array
VueComponent
VueComponent