ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript およびその他のガベージ コレクションを理解する

JavaScript およびその他のガベージ コレクションを理解する

Susan Sarandon
リリース: 2025-01-27 22:32:17
オリジナル
565 人が閲覧しました

Understanding Garbage Collection in JavaScript and Beyond

最近、技術面接で、さまざまなプログラミング言語がガベージ コレクションをどのように処理するかについて質問されました。これは驚くべき、しかし新鮮な質問であり、私の興味を非常に刺激しました。これまでのインタビューでメモリ管理についてこれほど詳細に議論されたのは初めてでした。この質問は気に入ったので、ブログ投稿でこのトピックをさらに詳しく掘り下げていきたいと思います。


高性能アプリケーションには効率的なメモリ管理が重要です。 ガベージ コレクション (GC) 未使用のメモリを自動的にリサイクルして、メモリ リークやクラッシュを防ぎます。この記事では、JavaScript でガベージ コレクションがどのように機能するかに焦点を当て、プログラミング言語で使用される他のメソッドを検討し、これらの概念を説明する例を示します。


ガベージコレクションとは何ですか?

ガベージ コレクションは、使用されなくなったオブジェクトによって占有されていたメモリを再利用するプロセスです。自動ガベージ コレクションを備えた言語ではこのプロセスが抽象化されるため、開発者は手動でメモリを管理する必要がありません。たとえば、JavaScript は トラッキング ガベージ コレクター を使用しますが、他の言語では異なる技術が使用されます。


JavaScript のガベージ コレクション

JavaScript は、トラッキング ガベージ コレクション メソッド、特に マーク スイープ アルゴリズムに依存しています。細かく見てみましょう:

1. マーククリアアルゴリズム

このアルゴリズムは、メモリ内のどのオブジェクトが「到達可能」であるかを判断し、到達不可能なオブジェクトを解放します。

  1. マークステージ:
    • 「ルート」オブジェクト (たとえば、ブラウザーの window または Node.js のグローバル オブジェクト) から開始します。
    • これらのルート オブジェクトから到達可能なすべてのオブジェクトを反復処理し、それらを「生きている」とマークします。
  2. クリアフェーズ:
    • ヒープをスキャンし、到達可能としてマークされていないオブジェクトを解放します。

例:

<code class="language-javascript">function example() {
  let obj = { key: "value" }; // obj 可达
  let anotherObj = obj; // anotherObj 引用 obj

  anotherObj = null; // 引用计数减少
  obj = null; // 引用计数减少到 0
  // obj 现在不可达,将被垃圾回收
}</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

2. 世代別ガベージコレクション

最新の JavaScript エンジン (Chrome/Node.js の V8 など) は、世代 GC を使用してガベージ コレクションを最適化します。メモリは次のように分割されます:

  • 新世代: 有効期間の短いオブジェクト (関数スコープ変数など) はここに保存され、頻繁に収集されます。
  • 古い世代: 存続期間の長いオブジェクト (グローバル変数など) はここに保管され、収集される頻度は低くなります。

世代別 GC の方が効率的なのはなぜですか?

  • JavaScript のほとんどのオブジェクトは一時的なものであり、すぐに収集できます。
  • 存続期間の長いオブジェクトは古い世代に移動され、頻繁なスキャンの必要性が軽減されます。

その他のガベージ コレクション戦略

他の言語がガベージ コレクションをどのように処理するかを調べてみましょう:

1. 参照カウント

参照カウントは、オブジェクトを指す参照の数を追跡します。参照カウントが 0 になると、オブジェクトは解放されます。

利点:

  • シンプルかつ即時のメモリ再利用。
  • 予測どおりに動作します。

欠点:

  • 循環参照: 2 つのオブジェクトが相互に参照している場合、それらのカウントが 0 になることはありません。

例: (Python 参照カウント)

<code class="language-javascript">function example() {
  let obj = { key: "value" }; // obj 可达
  let anotherObj = obj; // anotherObj 引用 obj

  anotherObj = null; // 引用计数减少
  obj = null; // 引用计数减少到 0
  // obj 现在不可达,将被垃圾回收
}</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

2. 手動メモリ管理

CC などの 言語では、開発者が明示的にメモリを割り当てて解放する必要があります。

例: (C メモリ管理)

<code class="language-python">a = []
b = []
a.append(b)
b.append(a)
# 这些对象相互引用,但不可达;现代 Python 的循环收集器可以处理这种情况。</code>
ログイン後にコピー
ログイン後にコピー

利点:

  • メモリ使用量を完全に制御します。

欠点:

  • メモリ リーク (メモリの解放の忘れ) やダングリング ポインタ (メモリの早期解放) が発生しやすくなります。

3. ループコレクターによるガベージコレクションの追跡

Python などの一部の言語では、参照カウントサイクル検出 を組み合わせて循環参照を処理します。

  • ループ コレクターはオブジェクトを定期的にスキャンして、ループ (ルート オブジェクトからアクセスできない相互参照オブジェクトのグループ) を検出します。ループが見つかると、コレクターはループを中断し、メモリを再利用します。
  • 循環コレクターは、純粋な参照カウント (循環参照) の最大の欠点を解決します。追加のオーバーヘッドが追加されますが、ループによるメモリ リークが発生しないようにします。

4. Rust の借用チェッカー (GC なし)

Rust は異なるアプローチを採用し、ガベージ コレクションを完全に回避します。代わりに、Rust は Borrow Checker を介して厳密な所有権ルールを適用します:

  • 所有権: 各値には一度に 1 人の所有者のみが存在します。
  • 借用: 参照 (不変または変更可能) を借用できますが、データ競合 を防ぐため、一度に許可される変更可能な参照は 1 つだけです。
  • ライフサイクル: コンパイラーは、値がスコープ外になると推測し、自動的にメモリーを解放します。

このシステムは、従来の GC を必要とせずにメモリの安全性を確保し、Rust に手動メモリ管理によるパフォーマンス上の利点をもたらしながら、ダングリング ポインタなどのよくある間違いを回避するのに役立ちます。

追加説明。 #データ競合は、2 つ以上のスレッド (またはプロセス) が同じメモリ位置に同時にアクセスし、少なくとも 1 つのスレッドがその位置に書き込む場合、同時プログラミングまたは並列プログラミングで発生します。これらの同時アクセスを調整するメカニズム (ロックやアトミック操作など) がないため、共有データの最終状態は予測不能で一貫性がなく、発見が困難なエラーにつながる可能性があります。


ガベージリサイクル戦略はを比較します

---
方法 语言 优点 缺点
引用计数 早期的 Python,Objective-C 立即回收,易于实现 循环引用失效
追踪式(标记-清除) JavaScript,Java 处理循环引用,对于大型堆效率高 停止世界暂停
分代式 GC JavaScript,Java 针对短暂的对象进行了优化 实现更复杂
手动管理 C,C 完全控制 容易出错,需要仔细处理
混合式(引用计数 循环收集器) 现代 Python 两全其美 仍然需要定期的循环检测
借用检查器 Rust 无需 GC,防止数据竞争 学习曲线较陡峭,所有权规则
JavaScript一般的なシーンに対処する方法

円形の参照

JavaScriptの追跡ゴミ回復は、周期的な参照を処理できます:

イベントの監視と閉鎖

<code class="language-javascript">function example() {
  let obj = { key: "value" }; // obj 可达
  let anotherObj = obj; // anotherObj 引用 obj

  anotherObj = null; // 引用计数减少
  obj = null; // 引用计数减少到 0
  // obj 现在不可达,将被垃圾回收
}</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
インシデントモニターが正しくクリーニングされていない場合、誤ってメモリの漏れを引き起こす可能性があります:

概要

<code class="language-python">a = []
b = []
a.append(b)
b.append(a)
# 这些对象相互引用,但不可达;现代 Python 的循环收集器可以处理这种情况。</code>
ログイン後にコピー
ログイン後にコピー

JavaScriptは、管理メモリの動員から

アルゴリズムから追跡されたゴミ回復を使用します。

    短いオブジェクトに注意を払うことにより、分割されたGC
  1. パフォーマンスを最適化します。 さまざまな戦略では、他の言語を使用しています: リファレンスカウント
  2. :シンプルですが発生しやすいです。
  3. マニュアル管理:完全に制御されているが間違いを犯しやすい。
  4. Mixed Method
      :より良いパフォーマンスを得るための戦略と組み合わされます。
    • rustの借入検査装置:GCはありませんが、厳しい所有ルールがあります。
    • JavaScriptの潜在的なメモリリーク、特に閉鎖やイベントモニタリングに注意してください。
    • これは、ゴミリサイクル戦略の言語を理解する絶好の機会です。私の意見では、ゴミリサイクルの実用的な原則を理解することは、効率的なコードの作成に役立つだけでなく、メモリに関連するエラーを効果的にデバッグすることもできます。
    • リファレンス
    javascriptとメモリ管理:MDNドキュメント
  5. V8ゴミリサイクル:V8ゴミリサイクルについてのブログ
Rustの所有権:Rustプログラミング言語帳

Java Garbage Recycling:Oracle Document

PythonのGC:Python GCモジュール

以上がJavaScript およびその他のガベージ コレクションを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート