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

ガベージコレクションは、JavaScriptのメモリ管理の仕組みで、使用されなくなったオブジェクトを削除し、メモリを解放する。

実行は、ガベージコレクタと呼ばれる、バックグラウンドプロセスにより自動的に実行される。ガベージコレクタはオブジェクトを監視し、到達不可能になったオブジェクトを削除する。

C++とかだと、デストラクタやスマートポインタなどをプログラマが用いることで実現する管理を、JSではガベージコレクタが自動実行してくれる。素晴らしい🧐

到達性

JavaScriptのメモリ管理の主要コンセプトは到達性で、『到達可能な』値とは、何らかの形でアクセス可能、もしくは使用可能な値のことを指す。それらの値はガベージコレクタにより削除されず、メモリに格納されることが保証される。

具体的な例をいくつか示す。

  • 本質的に到達可能な値の基本セット(ルートと呼ばれる)
    • 実行中の関数のローカル変数とパラメータ
    • ネストされた呼び出しの関連する他関数のローカル変数とパラメータ
    • グローバル変数
  • 上記以外は、参照または参照チェーンにより、ルートから到達可能できるもの

    例えば、ローカル変数にオブジェクトAがあり、オブジェクトAがオブジェクトBへの参照を持っている場合、オブジェクトBは到達可能とみなされる。

到達性の例

  • シンプルなパターン

    例えば、次のようなオブジェクトがあるとする。

  let user = {
    name: "John"
  };

参照を図示すると次のような感じ。

image.png

ここで、user の値を上書きすると、オブジェクトへの参照がなくなり到達不可能になり、ガベージコレクタによりオブジェクトは破棄される。

  user = null;

image.png

  • 2つの参照がある場合

    例えば、次のようなオブジェクトがあるとする。

  let user = {
    name: "John"
  };

  let admin = user;

image.png

シンプルな例と同様に、user を上書きしても、オブジェクトへの参照は admin からのものが残っているためオブジェクトは削除されない。admin の値を上書きするとオブジェクトは削除される。

  • 連結されたオブジェクト

    次のようなオブジェクトを考える。

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

    return {
      father: man,
      mother: woman
    }
  }

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

image.png

上記の通り、すべてのオブジェクトはルート(<global variale>)から到達可能になっている。

2つの参照を削除してみる。

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

image.png

name: "Ann" のオブジェクトは到達可能だが、name: "John" のオブジェクトはルートから到達できるなくなるため、ガベージコレクタにより削除される。

  • 到達不可能な島

    連携されたオブジェクトの全体が到達不可能になり、メモリから削除される場合もある。例えば、上の family で示した例において、family の参照を削除してみる。

  family = null;

image.png

family から参照が消えたことで、ルートから参照できなくなり、島全体が到達不可能になったため削除されることになる。

ガベージのアルゴリズム

ガベージは、『マークアンドスイープ』と呼ばれる方法で行われる。具体的には次の手順が定期的に実行される。

  1. ガベージコレクタはルートを取得し、 それらを “マーク” (記憶)する
  2. 次に、そこからのすべての参照先を訪れ、マークする
  3. 次に、マークされたオブジェクトへアクセスし、それらの参照をマークする
  4. 上記を繰り返し、すべての到達可能な(ルートからの)参照が訪問されるまで続ける
  5. マークされたオブジェクトを除いた、すべてのオブジェクトが削除されます。

例えば、次のようなオブジェクトを考える。

image.png

右側のオブジェクトは、明らかに島全体が到達不可能な島になっている。ガベージコレクタがどう処理するかを追う。

  1. ルートをマークする

    image.png

  2. ルートの参照をマークする

    image.png

  3. それらの参照も辿れるところまでマークする

    image.png

  4. マークされていないオブジェクトを到達不可能と見做し、削除する

    image.png

参考