自動メモリ管理

newobj命令

  1. バイト数計算(型・フィールド)
  2. バイト数にオーバーヘッド領域(型オブジェクトポインタ・同期ブロックインデックス)を加で必要となる分を加算
    • 8バイト(64ビットアプリケーションなら16バイト)
  3. 予約領域を確認
    1. 確保できるならNextObjPtrが指すアドレスに確保
    2. バイトをゼロクリア
    3. コンストラクタ呼出
  4. NextObjPtrを進める
  5. オブジェクトのアドレスを返す

ガベージコレクション

ルート

参照型オブジェクトのメモリポインタの位置。

OutOfMemoryException

ガベージコレクションの後でヒープに空きメモリが存在しない場合、new演算子を実行するとthrowされる。

ガベージコレクション
  1. すべてをゴミと仮定
  2. マーキング
    • スレッドスタックをさかのぼり、ルートをチェック
    • ルート見つける→同期ブロックインデックスのビットをオン(これが「マーク」)
    • 到達可能なすべてのオブジェクトを再帰的に辿り続ける
      • すでにマークされたオブジェクトを発見すると、それ以上の探索は中止する
        • パフォーマンス向上と、循環参照による無限ループ対策のため
  3. コンパクト化
    • 大きな連続したブロックを見つけてオブジェクトを移動させる
    • 移動したオブジェクトを参照しているフィールドを修正
  4. NextObjPtrをゴミではない最後のオブジェクトの直後の場所へ移動
ガベージコレクションの契機
  • ジェネレーション0が満杯になる
  • GC.Collect呼出
  • メモリ不足の通知
  • AppDomainアンロード
  • CLR終了(このときはFinalize呼出のみでコンパクト化は実施しない)

ファイナライゼーション

  • Finalize
  • クリーンな後処理のためのメカニズム
  • 呼び出すタイミングはガベージコレクタ任せ
  • ガベージコレクト完了時に呼び出される
ファイナライゼーションリスト
Fリーチャブルキュー
  • Finalize用の優先度の高いスレッドがFinalize呼出を担当。
  • Fリーチャブルキューにエントリが入るとスレッドが活性化
  • キューからエントリを削除し、オブジェクトのFinalizeメソッドを呼び出す
  • Fリーチャブルキューが参照している限り、オブジェクトはガベージコレクションの対象にはならない(=Finalize呼出が完了して初めて、オブジェクトはガベージコレクションの対象となり、削除される)

ジェネレーション

CLRガベージコレクタがアプリケーションパフォーマンス向上に使用するメカニズムを「ジェネレーション」という。(いわゆる世代別GC)
http://d.hatena.ne.jp/qnzm/20081115/1226763989

ガベージコレクションのパフォーマンス

開始のために
  1. 全てのスレッドを一斉に一時停止し、スレッドがどこを実行しているか確認
  2. 全てのスレッドがセーブポイントに到達するか乗っ取りができたら、ガベージコレクションを開始できる。
    • なお、アンマネージコードを実行してるスレッドは一時停止しない
    • セーブポイントに到達
      • スレッド命令ポインタがメソッドテーブルに記述されたオフセットに入ったとき
        • ここでいうテーブルは、JITコンパイラが生成したネイティブコードが持つ内部のテーブルのこと
      • 一時停止しても問題ない地点
    • 乗っ取り
      • セーブポイントにないスレッドに対して実施
      • CLRがスタックのリターンアドレスを特殊な関数を指すように書き換える
      • この特殊な関数はスレッドを一時停止する
ガベージコレクションの構成
  • サーバモード(gcServer)
    • CPUごとに一つのスレッド。
    • それぞれのスレッドが他のスレッドと並列に自分の担当セクションの回収作業を実施。
    • ASP.NETSQL Serverなどのホストアプリケーションで利用
  • gcConcurrent