C#のガベージコレクションって何してるの?

はじめに

どうも、にとです!
C#ってメモリ解放とかを勝手にやってくれるのですが、中でどんな風に動いているのか気になったので本棚に眠っていたオライリーの本を参考にして簡単にまとめてみました。

ガベージコレクションとは

ヒープブロックの割り当てを解除するタイミングを決定する機能。

ヒープ

ヒープとは動的に確保と解放を繰り返せるメモリ領域のことです。インスタンスをnewするなどで新しいヒープブロックが割り当てられます。
ヒープブロックにはオブジェクトの静的ではないすべてのフィールド(配列ならすべての要素)とヘッダが含まれる

1.オブジェクトの生存を決定する

まずは使っていないオブジェクトを判別するにはルートを決めます。

ルート

まずルートとは何かというと、「到達可能なオブジェクトへの参照」です。つまり今どこかで使われていて生存しているオブジェクトへの参照のことです。
他にも参照型の静的フィールドなど、プログラムが別のオブジェクト参照を経由しなくても将来必ず利用できるオブジェクトへの参照もルートになります。

ルートであるかの判定

ルートであるかは以下の条件で判断されます。

  • そのオブジェクトへの参照がnullでなければルート
  • ルートであるオブジェクトが参照しているオブジェクトもルート

※ローカル変数、メソッド引数はその生存期間だけルートになる(引数は渡した時点で終了)
※式の評価の結果として生成される一時オブジェクトも評価が完了するまで生存する

弱参照

弱参照を使うとオブジェクトへの到達可能性が若干変わります。

普通の参照と何が違う?

オブジェクトが弱参照からしか到達できないときはGCで割り当てを解放します。

つまり

  • 「自分以外が全員参照を手放したら、その時点で解放対象にしてほしい」
  • 「オブジェクトを参照しているけれど、GC的には参照してることにしないでほしい」

ときに使う

弱参照の宣言

WeakReference<T> hoge = new WeakReference<T>(value);
// コンストラクタ引数に渡したもので初期化される
// Tの部分は任意の型を指定する

2.メモリの回収

オブジェクトが死亡するとその分のメモリが回収され、ヒープに空き領域ができます。このとき新しく必要になったメモリを空のブロックにそのまま割り当てると無駄が多くなってしまいます。

そこで登場するのがコンパクションという処理です。

コンパクション

コンパクションとはヒープの空き領域が連続的になる状態にする処理のことです。これをすることで、

  • 新しいメモリを無駄なく割り当てられる
  • 関連するデータが近くになるので効率が良くなる

という利点があります。

ブロックを移動したときにはすべてのポインタを調整します。

この方法で万事解決...と思いきやもう一つ問題があります。それは古いオブジェクトが到達不能になったときにコンパクションに時間がかかってしまうというものです。

このようにオブジェクトの生存期間によってコンパクションのコストが変わってしまいます。そこでオブジェクトを世代に分けて考えます。

世代

オブジェクトの生存期間によるコンパクションのコストの違いを考慮し、オブジェクトを3つの世代に分け、世代によってGCのタイミングを変えます。

  • 世代0 … まだ一度もGCを経験していないオブジェクト
  • 世代1 … 短命か長命かを見極める待期期間

ここまでが短命世代と呼ばれ、世代1までの領域が閾値を超えると通常GCが発生します。

  • 世代2 … もっとも古い世代
    世代2まで生き残ったオブジェクトは
    • フルGCのときのみメモリが回収される
    • コンパクションに時間がかかる
    • CPUのキャッシュが消えていてコピーに時間がかかる

    (※世代2に入るがそれほど寿命が長くないオブジェクトができることを中年の危機と呼ぶらしい)

世代1まではプログラムが動いているときのGCによってメモリを回収し、世代2はフルGCのときのみメモリが回収されます。

大規模オブジェクトヒープ(LOH)

サイズが大きいオブジェクト(85000バイト以上)は大規模オブジェクトヒープと呼ばれるヒープに割り当てられます。コストがかかるため通常GCではコンパクションをせず、フルGCのときに明示的に要求しないとコンパクションはできません。

感想

今まで裏で動いているものや実際の開発でそれほど使わないような知識は結構すっ飛ばしていたんですが、こうやって調べてみると意外と面白かったです。Unity開発でもプロファイラを見るとたまにGCによってパフォーマンスがガクッと下がっていることがあるので、GCの仕組みと特性を生かした対処ができたらいいなと思いました。

参考

www.amazon.co.jp