ホームページ >ウェブフロントエンド >jsチュートリアル >jsガベージコレクションの内容について簡単に説明しましょう

jsガベージコレクションの内容について簡単に説明しましょう

不言
不言オリジナル
2018-07-16 09:42:222244ブラウズ

この記事では、主に js のガベージ コレクションのメカニズムを紹介します。これは、必要な友人に参考にしていただけるようになりました。

メモリ管理は自動的に行われ、私たちには見えません。私たちが作成するプリミティブ型、オブジェクト、関数などはすべてメモリを占有します。

必要なくなったらどうなりますか? JavaScript エンジンはどのようにしてそれらを見つけてクリアするのでしょうか?

到達可能性

JavaScript のメモリ管理における重要な概念は、

到達可能性

です。 簡単に言うと、「到達可能な」値はアクセス可能で利用可能であり、メモリに安全に保存されます。

    以下は、「タッチ可能」である必要があり、いかなる理由でも削除できない値の一部です:
    現在の関数のローカル変数とパラメーター。
  • 現在のネストされた呼び出しチェーン内のすべての関数のローカル変数とパラメーター。
  • グローバル変数。
  • (および他の内部変数)
这些值都称为 *roots*。
    他の値が到達可能かどうかは、ルートとその参照チェーンによって参照されているかどうかによって決まります。
  1. ローカル変数にオブジェクトが存在し、その値が別のオブジェクトを参照しているとします。このオブジェクトが参照できる場合、そのオブジェクトが参照するオブジェクトも参照できます。詳細な例は後で説明します。

  2. JavaScript エンジンには、ガベージ コレクション) のバックグラウンド プロセスがあります。すべてのオブジェクトを監視し、到達不能になった場合は削除します。

簡単な例

// user has a reference to the object
let user = {
  name: "John"
};

jsガベージコレクションの内容について簡単に説明しましょう 矢印はオブジェクト参照を表します。グローバル変数 "user" は、オブジェクト {name: "John"} (John と呼ばれます) を参照します。 John の "name" 属性にはプリミティブ値が格納されるため、他に参照はありません。

user を上書きすると、John への参照が失われます: "user" 引用了对象{name: "John"}(简称此对象为 John)。John 的 "name" 属性储存的是一个原始值,所以无其他引用。

如果覆盖 user,对 John 的引用就丢失了:

user = null;

jsガベージコレクションの内容について簡単に説明しましょう

现在 John 变得不可触及,垃圾回收机制会将其删除并释放内存。

两个引用

如果我们从 user 复制引用到 admin

// user has a reference to the object
let user = {
  name: "John"
};

*!*
let admin = user;
*/!*

jsガベージコレクションの内容について簡単に説明しましょう

如果重复一次这个操作:

user = null;

……这个对象是依然可以通过 admin 访问的,所以它依然存在于内存。如果我们把 admin 也覆盖为 null,那它就会被删除了。

相互引用的对象

这个例子比较复杂:

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  }
}

let family = marry({
  name: "John"
}, {
  name: "Ann"
});

marry 函数让两个参数对象互相引用,返回一个包含两者的新对象,结构如下:

jsガベージコレクションの内容について簡単に説明しましょう

暂时所有对象都是可触及的,但我们现在决定移除两个引用:

delete family.father;
delete family.mother.husband;

jsガベージコレクションの内容について簡単に説明しましょう

只删除一个引用不会有什么影响,但是两个引用同时删除,我们可以看到 John 已经不被任何对象引用了:

jsガベージコレクションの内容について簡単に説明しましょう

即使 John 还在引用别人,但是他不被别人引用,所以 John 现在已经是不可触及的了,它的存在将会被移除。

垃圾回收后:

jsガベージコレクションの内容について簡単に説明しましょう

孤岛(Unreachable island)

也可能有一大堆互相引用的对象整块(像个孤岛)都不可触及了。

对上面的对象进行操作:

family = null;

内存中的情况如下:

jsガベージコレクションの内容について簡単に説明しましょう

这个例子展示了“可触及”这个概念的重要性。

尽管 John 和 Ann 互相依赖,但这仍不足够。

"family"rrreee

jsガベージコレクションの内容について簡単に説明しましょう🎜🎜これで John はアンタッチャブルになり、ガベージ コレクション メカニズムによってジョンは削除され、メモリが解放されます。 🎜🎜2 つの参照🎜🎜 user から admin に参照をコピーすると: 🎜rrreee🎜jsガベージコレクションの内容について簡単に説明しましょう🎜🎜この操作を繰り返すと 🎜rrreee🎜...これオブジェクトはい、admin を通じて引き続きアクセスできるため、メモリ内にまだ存在します。 admin も null に上書きすると、削除されます。 🎜🎜相互参照するオブジェクト🎜🎜 この例はより複雑です: 🎜rrreee🎜marry この関数は 2 つのパラメーター オブジェクトを相互参照させ、両方を含む新しいオブジェクトを返します。構造は次のとおりです。 🎜jsガベージコレクションの内容について簡単に説明しましょう🎜🎜 現時点ではすべてのオブジェクトに到達可能ですが、次の 2 つの参照を削除することにしました: 🎜rrreee🎜jsガベージコレクションの内容について簡単に説明しましょう🎜🎜 1 つの参照だけを削除しても影響はありませんが、両方の参照を同時に削除すると、次のことがわかります。 John はもういません 参照されているオブジェクト: 🎜🎜 4016353222-5b4b1e030b7a0_articlex [1].png🎜🎜ジョンは依然として他者を参照していますが、他者によって引用されていないため、ジョンはアンタッチャブルとなり、彼の存在は削除されます。 🎜🎜ガベージコレクション後: 🎜🎜2369010816- 5b4b1e02ecc22_articlex[1].png🎜🎜到達不能な島🎜🎜 相互に参照するオブジェクトが多数あり、ブロック全体 (島など) が到達不能になる可能性もあります。 🎜🎜上記のオブジェクトに対する操作: 🎜rrreee🎜 メモリ内の状況は次のとおりです: 🎜🎜jsガベージコレクションの内容について簡単に説明しましょう🎜🎜この例は、「到達可能性」の概念の重要性を示しています。 🎜🎜ジョンとアンはお互いを頼りにしていましたが、それだけでは十分ではありませんでした。 🎜🎜"family" オブジェクト全体がルート接続から切り離されており、何も参照していないため、この島は手の届かないところにあり、削除されるのを待つしかありません。 🎜

内部アルゴリズム

基本的なガベージ コレクション アルゴリズムは、「マーク アンド スイープ」と呼ばれます:

  • ガベージ コレクターはルートを取得してマークします。

  • 次に、それらからのすべての引用にアクセスしてタグを付けます。

  • マークされたオブジェクトにアクセスするには、それらの 参照をマークします。訪問したオブジェクトはすべて記録され、今後同じオブジェクトが繰り返しアクセスされることはありません。

  • …未訪問の参照だけが残るまで。

  • マークされていないオブジェクトはすべて削除されます。

オブジェクトの構造が次のとおりであると仮定します。

jsガベージコレクションの内容について簡単に説明しましょう

右側に「島」がはっきりと見えます。ここで、「マークしてクリア」方法を使用してこれに対処します。

最初のステップ、ルートをマークします:

jsガベージコレクションの内容について簡単に説明しましょう

次に、それらの参照をマークします:

jsガベージコレクションの内容について簡単に説明しましょう

... 参照されている参照をマークします:

jsガベージコレクションの内容について簡単に説明しましょう

これで、アクセスされていないオブジェクトはアクセスできないとみなされます。削除されます:

jsガベージコレクションの内容について簡単に説明しましょう

これがガベージ コレクションの仕組みです。

JavaScript エンジンは、実行に影響を与えることなく多くの最適化を行い、このプロセスのガベージ コレクションの効率を高めました:

  • 世代コレクション -- オブジェクトは「新しい世代」と「古い世代」に分割されます。多くのオブジェクトはタスクが完了するとすぐに不要になるため、頻繁にクリーンアップできます。除染中に取り残された人々は「旧世代」と呼ばれる。

  • 増分コレクション -- オブジェクトが多数ある場合、すべてのオブジェクトを一度にマークすることは難しく、このプロセスによりプログラムの実行に大幅な遅延が発生することもあります。したがって、エンジンはこの操作を複数の部分に分割し、一度に 1 つの部分を実行しようとします。これを行うには追加のデータを記録する必要がありますが、ユーザー エクスペリエンスに対する遅延の影響を効果的に軽減できます。

  • アイドル時間収集 -- ガベージ コレクターは、プログラムの実行への影響を軽減するために、CPU がアイドル状態のときにのみ実行しようとします。

さらに、ガベージ コレクションには多くの最適化がありますが、ここでは詳しく説明しません。各エンジンには独自の調整とテクノロジがあり、これは実用的でない場合は常に変更されます。ニーズをあまり深く掘り下げる価値はありません。ただし、これに本当に興味がある場合は、いくつかの拡張リンクが以下に提供されます。

概要

重要なポイント:

  • ガベージコレクションは自動的に行われ、強制したり停止したりすることはできません。

  • 到達可能なオブジェクトはメモリに保持されます。

  • 参照は必ずしも (ルートから) 到達可能であるとは限りません。相互に参照するオブジェクトは完全に到達不能になる可能性があります。

最新のエンジンは強化されたガベージ コレクション アルゴリズムを実装しており、それらについては書籍『ガベージ コレクション ハンドブック: 自動メモリ管理の技術』(R. Jones et al.) で言及されています。

低レベル プログラミングに精通している場合は、「V8 のツアー: ガベージ コレクション」を読んで、V8 ガベージ コレクションの詳細を学ぶことができます。

V8 ブログでもメモリ管理に関する記事を頻繁に公開しています。ガベージ コレクション アルゴリズムを学ぶ最良の方法は、まず V8 実装を学び、Vyacheslav Egorov (V8 エンジニアの 1 人) のブログを読むことです。 V8 と言ったのは、インターネット上に V8 に関する記事がたくさんあるからです。他のエンジンの場合、多くの実装は類似していますが、ガベージ コレクション アルゴリズムには多くの違いがあります。

エンジンを深く理解することは、低レベルの最適化を行うときに非常に役立ちます。言語に慣れてきたら、これを追求するのが賢明な方向です。

上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連する推奨事項:

ページがPCで開かれたかモバイルで開かれたかをJSで判断する方法

JSのプロトタイプの詳細説明

以上がjsガベージコレクションの内容について簡単に説明しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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