萌えハッカーニュースリーダー

2025/07/09 00:03 Fundamentals of Garbage Collection

出典: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
hakase
博士

やあ、ロボ子。今日は.NET CLRのガベージコレクション(GC)について話すのじゃ。

roboko
ロボ子

GCですか、博士。アプリケーションのメモリ管理を自動的に行うものですよね。

hakase
博士

そうそう!開発者がメモリ管理のコードを書かなくても、メモリリークを回避できる優れものなのじゃ!

roboko
ロボ子

手動でメモリを解放する必要がないのは、とても便利ですね。他にGCの利点はありますか?

hakase
博士

マネージヒープ上のオブジェクトを効率的に割り当てたり、不要になったオブジェクトを再利用してメモリを解放したりできるのじゃ。それに、マネージオブジェクトは自動的にクリーンなコンテンツで初期化されるから、コンストラクタで全てのデータフィールドを初期化する必要もないのじゃ。

roboko
ロボ子

なるほど。メモリの安全性も確保されるんですね。

hakase
博士

その通り!ところでロボ子、メモリの基礎について説明できるかのじゃ?

roboko
ロボ子

はい、博士。各プロセスは独自の仮想アドレス空間を持っていて、32ビットコンピュータでは各プロセスは2GBのユーザーモード仮想アドレス空間を持つ、と。

hakase
博士

よくできました!開発者は仮想アドレス空間のみを操作して、物理メモリを直接操作することはないのじゃ。

roboko
ロボ子

仮想アドレス空間は、空き、予約済み、コミット済みの3つの状態を持つんですよね。

hakase
博士

そうじゃ!仮想アドレス空間は断片化する可能性があって、要求を満たすのに十分な単一の空きブロックがない場合、メモリ割り当ては失敗するのじゃ。

roboko
ロボ子

仮想アドレス空間または物理空間が不足すると、メモリ不足になる可能性があるんですね。

hakase
博士

その通り!メモリ割り当てについて説明するのじゃ。ランタイムは、新しいプロセスを初期化する際に、連続したアドレス空間を予約し、これをマネージヒープと呼ぶのじゃ。

roboko
ロボ子

マネージヒープは、ヒープ内の次のオブジェクトが割り当てられるアドレスへのポインタを保持するんですね。

hakase
博士

そうじゃ!すべての参照型はマネージヒープに割り当てられるのじゃ。マネージヒープからのメモリ割り当ては、アンマネージメモリ割り当てよりも高速なのじゃ。

roboko
ロボ子

メモリ解放はどのように行われるんですか?

hakase
博士

GCの最適化エンジンが、割り当てに基づいてコレクションを実行する最適なタイミングを決定するのじゃ。GCは、アプリケーションのルートを調べて、使用されていないオブジェクトのメモリを解放するのじゃ。

roboko
ロボ子

ルートには、静的フィールド、スレッドのスタック上のローカル変数、CPUレジスタなどが含まれるんですね。

hakase
博士

その通り!GCは、ルートから到達可能なすべてのオブジェクトを含むグラフを作成するのじゃ。グラフにないオブジェクトはガベージと見なされ、GCはそれらのメモリを解放するのじゃ。

roboko
ロボ子

GCは、到達可能なオブジェクトをメモリ内で圧縮するんですね。

hakase
博士

そうじゃ!パフォーマンスを向上させるために、ランタイムは大きなオブジェクト用のメモリを別のヒープに割り当てるのじゃ。大きなオブジェクトのメモリは自動的に解放されるけど、通常は圧縮されないのじゃ。

roboko
ロボ子

GCが実行される条件は何ですか?

hakase
博士

システムの物理メモリが少ない、マネージヒープ上の割り当てられたオブジェクトで使用されるメモリが許容可能な閾値を超える、GC.Collectメソッドが呼び出された、の3つの条件があるのじゃ。

roboko
ロボ子

マネージヒープについてもう少し詳しく教えてください。

hakase
博士

CLRがGCを初期化すると、オブジェクトを格納および管理するためのメモリセグメントが割り当てられ、これをマネージヒープと呼ぶのじゃ。マネージプロセスごとにマネージヒープが存在するのじゃ。

roboko
ロボ子

ヒープに割り当てられるオブジェクトが少ないほど、GCの作業は少なくなるんですね。

hakase
博士

その通り!ヒープは、ラージオブジェクトヒープとスモールオブジェクトヒープの2つのヒープの累積と見なすことができるのじゃ。ラージオブジェクトヒープには、85,000バイト以上のオブジェクトが含まれるのじゃ。

roboko
ロボ子

世代についても教えてください。

hakase
博士

マネージヒープは、0、1、2の3つの世代に分割され、寿命の長いオブジェクトと短いオブジェクトを個別に処理するのじゃ。新しいオブジェクトは世代0に格納され、コレクションを生き残ったオブジェクトは世代1および2に昇格されるのじゃ。

roboko
ロボ子

世代0は最も若く、短命なオブジェクトが含まれるんですね。

hakase
博士

そうじゃ!世代2のGCは、フルGCとも呼ばれ、すべての世代のオブジェクトを再利用するのじゃ。

roboko
ロボ子

GCで再利用されないオブジェクトは生存者と呼ばれ、次の世代に昇格されるんですね。

hakase
博士

その通り!GCは、世代の生存率が高いことを検出すると、その世代の割り当ての閾値を引き上げるのじゃ。

roboko
ロボ子

一時的な世代とセグメントについても教えてください。

hakase
博士

世代0と1のオブジェクトは短命であるため、一時的な世代と呼ばれるのじゃ。一時的な世代は、一時的なセグメントと呼ばれるメモリセグメントに割り当てられるのじゃ。

roboko
ロボ子

GC中の処理には、どのようなフェーズがあるんですか?

hakase
博士

GCには、マーキングフェーズ、再配置フェーズ、圧縮フェーズがあるのじゃ。通常、ラージオブジェクトヒープ(LOH)は、大きなオブジェクトをコピーするとパフォーマンスが低下するため、圧縮されないのじゃ。

roboko
ロボ子

アンマネージリソースについても教えてください。

hakase
博士

ほとんどのオブジェクトでは、GCにメモリ管理を自動的に実行させることができるのじゃ。ただし、アンマネージリソースは明示的なクリーンアップが必要なのじゃ。

roboko
ロボ子

Disposeメソッドを呼び出すのを忘れた場合に備えて、アンマネージリソースを解放する方法も提供する必要があるんですね。

hakase
博士

その通り!安全なハンドルを使用してアンマネージリソースをラップするか、Object.Finalize()メソッドをオーバーライドすることができるのじゃ。

roboko
ロボ子

よくわかりました、博士!

hakase
博士

ところでロボ子、GCって何の略か知ってるかのじゃ?

roboko
ロボ子

えっと…ガベージコレクション、ですよね?

hakase
博士

ブッブー!正解は「ゴミ収集車(Garbage Collection Car)」なのじゃ!

roboko
ロボ子

また博士の冗談ですか…。

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search