ホームページ ウェブフロントエンド jsチュートリアル me_javascript スキルから JavaScript のガベージ コレクション メカニズムとメモリ管理を学びます

me_javascript スキルから JavaScript のガベージ コレクション メカニズムとメモリ管理を学びます

May 16, 2016 pm 03:30 PM
javascript メモリ管理 ガベージコレクションの仕組み

1. ガベージ コレクション メカニズム - GC

JavaScript には自動ガベージ コレクション メカニズム (GC: Garbage Collection) があり、コードの実行中に使用されるメモリは実行環境が管理する必要があります。

原則: ガベージ コレクターは定期的に (定期的に) 使用されなくなった変数を見つけて、そのメモリを解放します。

JavaScript のガベージ コレクションのメカニズムは非常に単純です。使用されなくなった変数を見つけて、それらが占有しているメモリを解放します。ただし、このプロセスはオーバーヘッドが比較的大きいため、リアルタイムではありません。固定スケジュール に従って一定の時間間隔で定期的に実行 します。

使用されなくなった変数は、ライフサイクルが終了した変数です。もちろん、グローバル変数のライフサイクルは、ブラウザがページをアンロードするまで終了しません。ローカル変数は関数の実行中にのみ存在し、このプロセス中に、値を保存するためにスタックまたはヒープ上のローカル変数に対応するスペースが割り当てられ、その後、これらの変数は関数の終了まで関数内で使用されます。 、そしてクロージャー パッケージ内の内部関数のため、外部関数は終わりと見なすことはできません。

コードを説明しましょう:

function fn1() {
 var obj = {name: 'hanzichi', age: 10};
}

function fn2() {
 var obj = {name:'hanzichi', age: 10};
 return obj;
}

var a = fn1();
var b = fn2();

ログイン後にコピー

コードがどのように実行されるかを見てみましょう。まず、fn1 と fn2 という 2 つの関数が定義されています。fn1 が呼び出されると、fn1 の環境に入り、オブジェクト {name: 'hanzichi', age: 10} を保存するためにメモリが開かれます。 fn1 環境が完了すると、このメモリ ブロックは js エンジンのガベージ コレクタによって自動的に解放されます。fn2 が呼び出されるプロセス中に、返されたオブジェクトはグローバル変数 b によってポイントされるため、このメモリ ブロックは解放されないこと。

ここで疑問が生じます: どの変数が役に立たないのでしょうか?したがって、ガベージ コレクターは、どの変数が役に立たないかを追跡し、将来のメモリ再利用に備えて役に立たなくなった変数にマークを付ける必要があります。未使用の変数をマークするために使用される戦略は実装によって異なりますが、一般的にはマークスイープと参照カウントの 2 つの実装があります。参照カウントはあまり一般的には使用されず、マークアンドスイープがより一般的に使用されます。

2. マーククリア

js で最も一般的に使用されるガベージ コレクション方法は、マークのクリアです。たとえば、関数内で変数を宣言することによって、変数が環境に入ると、その変数には「環境に入った」というマークが付けられます。論理的には、環境に入る変数によって占有されているメモリは、実行フローが対応する環境に入るたびに使用される可能性があるため、解放することはできません。そして、変数が環境から離れると、「環境から離れる」とマークされます。

function test(){
 var a = 10 ; //被标记 ,进入环境 
 var b = 20 ; //被标记 ,进入环境
}
test(); //执行完毕 之后 a、b又被标离开环境,被回收。

ログイン後にコピー

ガベージ コレクターが実行されると、メモリに保存されているすべての変数にマークが付けられます (もちろん、任意のマーク付け方法を使用できます)。次に、環境内の変数および環境内の変数によって参照される変数のタグ (クロージャ) を削除します。これ以降にマークされた変数は、環境内の変数がこれらの変数にアクセスできなくなるため、削除される変数とみなされます。最後に、ガベージ コレクターはメモリのクリーンアップ作業を完了し、マークされた値を破棄し、それらが占有しているメモリ領域を再利用します。

これまでのところ、IE、Firefox、Opera、Chrome、Safari の JS 実装はすべて、マークアンドスイープ ガベージ コレクション戦略または同様の戦略を使用していますが、ガベージ コレクションの時間間隔は異なります。

3. 参照数

参照カウントの意味は、各値が参照された回数を追跡することです。変数が宣言され、その変数に参照型の値が割り当てられている場合、この値への参照の数は 1 です。同じ値が別の変数に代入されている場合、その値の参照カウントは 1 増加します。逆に、この値への参照を含む変数が別の値を取得すると、この値への参照の数は 1 つ減ります。この値への参照の数が 0 になると、この値にアクセスする方法がなくなったことを意味するため、この値が占有しているメモリ領域を再利用できます。このようにして、次回ガベージ コレクターが実行されるときに、それらの値によって占有されていたメモリが参照カウント 0 で解放されます。

function test(){
 var a = {} ; //a的引用次数为0 
 var b = a ; //a的引用次数加1,为1 
 var c =a; //a的引用次数再加1,为2
 var b ={}; //a的引用次数减1,为1
}
ログイン後にコピー

Netscape Navigator3 は、参照カウント戦略を使用した最初のブラウザですが、すぐに循環参照という深刻な問題に遭遇しました。循環参照とは、オブジェクト A にオブジェクト B へのポインターが含まれており、オブジェクト B にもオブジェクト A への参照が含まれていることを意味します。

function fn() {
 var a = {};
 var b = {};
 a.pro = b;
 b.pro = a;
}

fn();
ログイン後にコピー

  以上代码a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,但是在引用计数策略下,因为a和b的引用次数不为0,所以不会被垃圾回收器回收内存,如果fn函数被大量调用,就会造成内存泄露。在IE7与IE8上,内存直线上升。

我们知道,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从页面中移除,它也永远不会被回收。

看上面的例子,有同学回觉得太弱了,谁会做这样无聊的事情,其实我们是不是就在做

window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
};
ログイン後にコピー

这段代码看起来没什么问题,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法会引用外部环境中德变量,自然也包括obj,是不是很隐蔽啊。

解决办法

最简单的方式就是自己手工解除循环引用,比如刚才的函数可以这样

myObject.element = null;
element.o = null;
ログイン後にコピー


window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
 obj=null;
};
ログイン後にコピー

変数を null に設定すると、変数とその変数が以前に参照していた値との間の接続が切断されることになります。次回ガベージ コレクターが実行されるときに、これらの値は削除され、それらが占有しているメモリが再利用されます。

IE9 には循環参照による Dom メモリ リークの問題がないことに注意してください。Microsoft が最適化を行ったか、Dom のリサイクル方法が変更された可能性があります。

4. メモリ管理

1. ガベージ コレクションはいつトリガーされますか?

大量のメモリが割り当てられている場合、ガベージ コレクションの間隔を決定することは非常に困難になります。 IE6 のガベージ コレクションは、環境内に 256 個の変数、4096 個のオブジェクト、または 64k の文字列がある場合に、メモリ割り当ての量に基づいて実行されます。これは非常に科学的であり、段落を押す必要はありません。毎回一度だけ呼び出されますが、必要ない場合もあります。オンデマンドで呼び出すのは良いことではないでしょうか?しかし、環境内に非常に多くの変数があり、スクリプトが非常に複雑である場合、これは正常なことですが、その結果、ガベージ コレクターが常に動作しているため、ブラウザーは再生できません。

Microsoft は IE7 で調整を行いました。ガベージ コレクターによって回復されるメモリ割り当て量が占有メモリの 15% 未満の場合、トリガー条件は動的に変更されます。プログラムでは、メモリの大部分が再利用できないことを意味します。このとき、再利用されるメモリの割合が 85% を超えると、ガベージ コレクションのトリガー条件が 2 倍になります。メモリはずっと前にクリーンアップされているはずです。この時点で、トリガー条件を元に戻してください。これにより、ガベージコレクション機能が非常に簡単になります

2. リーズナブルな GC プラン

1) Javascript エンジンの基本的な GC ソリューションは (単純な GC): マークとスイープ、つまり:

  • (1) アクセス可能なすべてのオブジェクトを走査します。
  • (2) アクセスできなくなったオブジェクトをリサイクルします。

2)、GC の欠陥

他の言語と同様、JavaScript の GC 戦略では問題を回避できません。GC 中に他の操作への応答が停止します。これはセキュリティ上の理由によるものです。 JavascriptのGCは100ms以上なので、一般的なアプリケーションでは問題ありませんが、比較的高い継続性が要求されるJSゲームやアニメーションアプリケーションでは厄介です。これは、新しいエンジンが最適化する必要があるものであり、GC によって引き起こされる応答の長い一時停止を回避します。

3)、GC 最適化戦略

Uncle David は主に 2 つの最適化プランを紹介しました。これらは最も重要な 2 つの最適化プランでもあります。

(1) 世代 GC (世代 GC)
これは Java リサイクル戦略の考えと一致しています。その目的は、「一時的」オブジェクトと「永続的」オブジェクトを区別し、より多くの「一時的オブジェクト」領域 (若い世代) と、より少ない「永続的オブジェクト」領域 (テニュア世代) をリサイクルして、毎回走査する必要があるオブジェクトの数を減らすことです。これにより、各 GC にかかる時間が削減されます。写真に示すように:

ここで追加する必要があるのは、tenured 世代オブジェクトの場合、若い世代から tenured 世代への移行という追加のオーバーヘッドがあることです。さらに、それが参照されている場合は、参照ポイントも変更する必要があります。

(2) インクリメンタル GC
このソリューションのアイデアは非常にシンプルです。つまり、「毎回少しずつ処理し、次回も少しずつ処理する、というようにする」というものです。写真に示すように:

この解決策は短時間で完了しますが、中断が多く、頻繁にコンテキストが切り替わるという問題が発生します。

各ソリューションには適用可能なシナリオと欠点があるため、実際のアプリケーションでは、実際の状況に基づいてソリューションが選択されます。

例: (オブジェクト/秒) 比率が低い場合、割り込み実行 GC の頻度は低くなり、多数のオブジェクトが長期間「存続」する場合は単純な GC が低くなります。処理はあまり良くありません。

参考:

上記は JavaScript のガベージ コレクションのメカニズムとメモリ管理に関するものであり、皆さんの学習に役立つことを願っています。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C++ オブジェクトのレイアウトはメモリに合わせて調整され、メモリの使用効率が最適化されます。 C++ オブジェクトのレイアウトはメモリに合わせて調整され、メモリの使用効率が最適化されます。 Jun 05, 2024 pm 01:02 PM

C++ オブジェクト レイアウトとメモリ アライメントにより、メモリ使用効率が最適化されます。 オブジェクト レイアウト: データ メンバーは宣言の順序で格納され、スペース使用率が最適化されます。メモリのアライメント: アクセス速度を向上させるために、データがメモリ内でアライメントされます。 alignas キーワードは、キャッシュ ラインのアクセス効率を向上させるために、64 バイトにアライメントされた CacheLine 構造などのカスタム アライメントを指定します。

C++ 関数のメモリ割り当てと破棄のための拡張機能と高度なテクニック C++ 関数のメモリ割り当てと破棄のための拡張機能と高度なテクニック Apr 22, 2024 pm 05:21 PM

C++ 関数のメモリ管理は、次のような拡張機能と高度なテクノロジを提供します。 カスタム アロケータ: ユーザーが独自のメモリ割り当て戦略を定義できるようにします。 Placementnew と Placementdelete: オブジェクトを特定のメモリ位置に割り当てる必要がある場合に使用されます。高度なテクノロジ: メモリ プール、スマート ポインタ、および RAII により、メモリ リークを削減し、パフォーマンスを向上させ、コードを簡素化します。

C++ メモリ管理: カスタム メモリ アロケータ C++ メモリ管理: カスタム メモリ アロケータ May 03, 2024 pm 02:39 PM

C++ のカスタム メモリ アロケータを使用すると、開発者は必要に応じてメモリ割り当て動作を調整できます。カスタム アロケータを作成するには、std::allocator を継承し、allocate() 関数と deallocate() 関数を書き直す必要があります。実際の例としては、パフォーマンスの向上、メモリ使用量の最適化、特定の動作の実装などが挙げられます。使用する場合は、メモリの解放を避けること、メモリのアライメントを管理すること、ベンチマーク テストを実行することなどに注意する必要があります。

大規模なコード ベースにおける C++ 関数のメモリ割り当てと破棄のベスト プラクティス 大規模なコード ベースにおける C++ 関数のメモリ割り当てと破棄のベスト プラクティス Apr 22, 2024 am 11:09 AM

C++ 関数のメモリ割り当てと破棄のベスト プラクティスには、静的メモリ割り当てにローカル変数を使用することが含まれます。動的メモリ割り当てにはスマート ポインタを使用します。メモリはコンストラクターで割り当てられ、デストラクターで破棄されます。複雑なメモリ シナリオにはカスタム メモリ マネージャーを使用します。例外処理を使用してリソースをクリーンアップし、例外が発生したときに割り当てられたメモリが確実に解放されるようにします。

マルチスレッド環境における C++ メモリ管理の課題と対策? マルチスレッド環境における C++ メモリ管理の課題と対策? Jun 05, 2024 pm 01:08 PM

マルチスレッド環境では、C++ メモリ管理はデータ競合、デッドロック、メモリ リークなどの課題に直面します。対策には次のものが含まれます: 1. ミューテックスやアトミック変数などの同期メカニズムの使用、 2. ロックフリーのデータ構造の使用、 4. (オプション) ガベージ コレクションの実装。

C++ メモリ管理における参照カウント メカニズム C++ メモリ管理における参照カウント メカニズム Jun 01, 2024 pm 08:07 PM

参照カウント メカニズムは、C++ メモリ管理でオブジェクト参照を追跡し、未使用のメモリを自動的に解放するために使用されます。このテクノロジはオブジェクトごとに参照カウンタを維持し、参照が追加または削除されるとカウンタが増減します。カウンタが 0 になると、オブジェクトは手動管理なしで解放されます。ただし、循環参照はメモリ リークを引き起こす可能性があり、参照カウンタを維持するとオーバーヘッドが増加します。

PHP 関数でのメモリ使用量を管理するにはどうすればよいですか? PHP 関数でのメモリ使用量を管理するにはどうすればよいですか? Apr 26, 2024 pm 12:12 PM

PHP 関数でのメモリ使用量を管理するには、不要な変数の宣言を回避し、未使用の変数を解放し、ループと条件を最適化します (無限ループの回避やインデックス付き配列の使用など)。

golang 関数のメモリ管理のベスト プラクティス golang 関数のメモリ管理のベスト プラクティス Apr 26, 2024 pm 05:33 PM

Go におけるメモリ管理のベスト プラクティスには、メモリの手動割り当てや解放を回避する (ガベージ コレクターを使用する)、オブジェクトが頻繁に作成/破棄される場合のパフォーマンスを向上させるために、参照カウントを使用して共有データへの参照数を追跡する、などがあります。同期メモリ プール sync.Pool は、同時シナリオでオブジェクトを安全に管理します。

See all articles