コンピュータプログラミングにおいて、トレースガベージコレクションは、特定の「ルート」オブジェクトからの参照チェーンによって到達可能なオブジェクトをトレースし、残りのオブジェクトを「ガベージ」とみなして収集することによって、どのオブジェクトを解放(「ガベージコレクション」)すべきかを決定し、それらを収集する自動メモリ管理の一形態です。 [ 1 ]トレースは最も一般的なタイプのガベージコレクションであり、そのため「ガベージコレクション」は参照カウントなどの他の方法ではなく、トレース方法を指すことが多く、実装には多数のアルゴリズムが使用されています。
[ 2 ]非公式には、オブジェクトは、プログラム内の少なくとも 1 つの変数によって直接、または他の到達可能なオブジェクトからの参照を介して参照されている場合に到達可能であると言えます。より正確には、オブジェクトは 2 つの方法でのみ到達可能です。
「ガベージ」の到達可能性の定義は最適とは言えません。なぜなら、プログラムがオブジェクトを最後に使用したのが、そのオブジェクトが環境スコープから外れる前になる可能性があるからです。構文上のガベージ(プログラムが到達できないオブジェクト)と意味上のガベージ(プログラムが二度と使用しないオブジェクト)を区別することがあります。例えば、次のようになります。
Object x = new Foo (); Object y = new Bar (); x = new Quux (); /* この時点で、x に最初に割り当てられた Foo オブジェクトは * 決してアクセスされないことがわかります。構文的に無意味です。*//* 次のブロックでは、y は意味的にゴミである可能性があります。 * しかし、x.check_something()が何らかの値を返すまで、 * それを判断することはできません。 */ if ( x . check_something ()) { x . do_something ( y ); } System . exit ( 0 );セマンティックなゴミを正確に識別する問題は、部分的に決定可能であることが容易に示せる。オブジェクトを割り当てるプログラムは、任意の入力プログラムを実行する、そして使用するかつその場合に限り終了処理では、停止問題を解決するために意味的ガベージコレクタが必要になります。意味的ガベージ検出のための保守的なヒューリスティック手法は活発な研究分野ですが、実質的にすべての実用的なガベージコレクタは構文的ガベージに焦点を当てています。
このアプローチのもう一つの複雑な点は、参照型と非ボックス値型の両方を持つ言語では、ガベージコレクタがスタック上の変数やオブジェクト内のフィールドのうち、どれが通常の値でどれが参照であるかを何らかの方法で区別する必要があることです。メモリ上では、整数と参照は同じように見える可能性があります。ガベージコレクタは、要素を参照として扱って追跡するか、プリミティブ値として扱うかを知る必要があります。一般的な解決策の一つは、タグ付きポインタを使用することです。
ガベージコレクタは、ルートセットから直接的または間接的に参照されていないオブジェクトのみを回収できます。しかし、一部のプログラムでは弱い参照が必要となり、これはオブジェクトが存在する限り使用可能ですが、オブジェクトの寿命を延ばすものではありません。弱い参照に関する議論では、通常の参照が強い参照と呼ばれることもあります。オブジェクトは、たとえ弱い参照が残っていても、強い(つまり通常の)参照が存在しない場合にガベージコレクションの対象となります。
弱い参照とは、ガベージコレクタが気にしないオブジェクトへのポインタのことではありません。この用語は通常、適切に管理された特殊な参照オブジェクトのカテゴリに使用されます。これらのオブジェクトは、オブジェクトが消滅した後でも安全な値(通常は )になるnullため、安全に使用できます。ガベージコレクタに認識されない安全でない参照は、オブジェクトが以前存在していたアドレスを参照し続けることで、単に宙ぶらりんの状態になります。これは弱い参照ではありません。
実装によっては、弱い参照はサブカテゴリに分類されます。たとえば、Java 仮想マシンは、ソフト参照[ 2 ] 、ファントム参照[ 3 ]、通常の弱い参照[ 4 ]の 3 つの形式の弱い参照を提供します。ソフト参照されたオブジェクトは、ガベージ コレクタがプログラムのメモリが不足していると判断した場合にのみ、解放の対象となります。ソフト参照や通常の弱い参照とは異なり、ファントム参照は、参照するオブジェクトへのアクセスを提供しません。代わりに、ファントム参照は、参照されたオブジェクトがファントム到達可能になったときにガベージ コレクタがプログラムに通知できるようにするメカニズムです。オブジェクトは、メモリ内に存在し、ファントム参照によって参照されているが、ファイナライザが既に実行されている場合に、ファントム到達可能になります。同様に、.NET は、長い弱い参照 (復活を追跡) と短い弱い参照[ 5 ]の 2 つの弱い参照のサブカテゴリを提供します。
弱い追跡機能を備えたデータ構造も考案できます。例えば、弱いハッシュテーブルが便利です。通常のハッシュテーブルと同様に、弱いハッシュテーブルはオブジェクトのペア間の関連付けを保持し、各ペアはキーと値として理解されます。ただし、ハッシュテーブルはこれらのオブジェクトへの強い参照を実際には保持しません。キーまたは値、あるいはその両方がガベージになった場合、特別な動作が発生します。ハッシュテーブルのエントリは自動的に削除されます。さらに、弱いキーのみを持つハッシュテーブル(値の参照は通常の強い参照)や、弱い値のみを持つハッシュテーブル(キーの参照は強い参照)など、より洗練されたものも存在します。
弱いハッシュテーブルは、オブジェクト間の関連付けを維持するために重要です。関連付けに関与するオブジェクトは、プログラム内で(関連付けを行うハッシュテーブル以外で)参照されなくなった場合、ガベージになる可能性があります。
このような目的で通常のハッシュテーブルを使用すると、「論理メモリリーク」、つまりプログラムが必要とせず使用しないアクセス可能なデータが蓄積されるという問題が発生する可能性があります。
トレースコレクタは、メモリのワーキングセットをトレースするため、このように呼ばれています。これらのガベージコレクタは、サイクルでガベージコレクションを実行します。メモリマネージャが割り当て要求を満たすのに十分な空きメモリがない場合にサイクルがトリガーされるのが一般的です。しかし、サイクルはミューテーターによって直接要求されたり、時間スケジュールに基づいて実行されたりすることもよくあります。元の方法は、メモリセット全体を複数回アクセスする単純なマークアンドスイープ方式でした。

単純なマークアンドスイープ方式では、メモリ内の各オブジェクトには、ガベージコレクション専用のフラグ(通常は1ビット)が割り当てられています。このフラグは、ガベージコレクションサイクル中を除き、常にクリアされます。
最初の段階はマーク付けの段階で、ルートセット全体をツリー走査し、ルートが指す各オブジェクトを「使用中」としてマークします。それらのオブジェクトが指すすべてのオブジェクトも同様にマークされるため、ルートセットを介して到達可能なすべてのオブジェクトがマークされます。
第2段階であるスイープ段階では、メモリ全体が最初から最後までスキャンされ、使用済みまたは未使用のブロックがすべて調べられます。使用中としてマークされていないブロックは、どのルートからもアクセスできないため、メモリが解放されます。使用中としてマークされたオブジェクトについては、使用中フラグがクリアされ、次のサイクルに備えます。
この方法にはいくつかの欠点があり、最も顕著なのは、データ収集中にシステム全体を一時停止する必要があることです。ワーキングセットの変更は一切許可されません。そのため、プログラムが定期的に(そして一般的には予測不能に)「フリーズ」する可能性があり、リアルタイム処理や時間制約の厳しいアプリケーションの一部が実行不可能になります。さらに、ワーキングメモリ全体を検査する必要があり、その多くは2回検査されるため、ページングメモリシステムでは問題が発生する可能性があります。

こうしたパフォーマンス上の問題から、最新のトレース型ガベージコレクタのほとんどは、3色マーキング抽象化の何らかのバリエーションを実装していますが、単純なコレクタ(マークアンドスイープコレクタなど)では、この抽象化を明示的に実装していないことがよくあります。3色マーキングは、以下のように動作します。
白、黒、グレーの3つのセットが作成されます。
多くのアルゴリズムでは、最初は黒色の集合は空であり、灰色の集合はルートから直接参照されるオブジェクトの集合であり、白色の集合はその他のすべてのオブジェクトを含みます。メモリ内のすべてのオブジェクトは、常に3つの集合のうちの1つにのみ属します。アルゴリズムは次のように進行します。
灰色の集合が空になった時点でスキャンは完了です。黒いオブジェクトはルートから到達可能ですが、白いオブジェクトは到達不可能であり、ガベージコレクションの対象となります。
ルートから直接到達できないオブジェクトはすべて白の集合に追加され、オブジェクトは白から灰色、灰色から黒へしか移動できないため、このアルゴリズムは重要な不変条件、すなわち黒のオブジェクトが白のオブジェクトを参照しないという条件を維持します。これにより、灰色の集合が空になった時点で白のオブジェクトを解放できることが保証されます。これは三色不変条件と呼ばれます。このアルゴリズムのいくつかのバリエーションでは、この不変条件は維持されませんが、重要な特性がすべて満たされる修正された形式が使用されます。
3色方式には重要な利点があります。それは、システムを長時間停止させることなく、「オンザフライ」で実行できることです。これは、オブジェクトが割り当てられる際や変更される際に、さまざまなセットを維持することで実現されます。セットのサイズを監視することで、システムは必要に応じてではなく、定期的にガベージコレクションを実行できます。また、各サイクルで作業セット全体にアクセスする必要もなくなります。
到達不能オブジェクト群が特定されると、ガベージコレクタは到達不能オブジェクトを解放して他のオブジェクトをそのままにしておく場合もあれば、到達可能なオブジェクトの一部または全部を新しいメモリ領域にコピーし、必要に応じてそれらのオブジェクトへの参照をすべて更新する場合もあります。これらはそれぞれ「非移動型」および「移動型」(または「非圧縮型」および「圧縮型」)ガベージコレクタと呼ばれます。
移動アルゴリズムは、各サイクルでより多くの処理が必要になるように見えるため、非移動アルゴリズムに比べて非効率に思えるかもしれません。しかし、移動アルゴリズムは、ガベージコレクションサイクル自体とプログラム実行の両方において、いくつかのパフォーマンス上の利点をもたらします。
移動型ガベージコレクタの欠点の 1 つは、ガベージ コレクション環境によって管理される参照を介してのみアクセスが許可され、ポインタ演算が許可されないことです。これは、ガベージ コレクタがオブジェクトを移動すると、オブジェクトへのポインタが無効になるためです (ダングリング ポインタになります)。ネイティブ コードとの相互運用性を確保するには、ガベージ コレクタはオブジェクトの内容をメモリのガベージ コレクション領域外の場所にコピーする必要があります。別のアプローチは、オブジェクトをメモリに固定し、ガベージ コレクタがそれを移動できないようにして、メモリをネイティブ ポインタと直接共有できるようにすることです (場合によってはポインタ演算も可能になります)。[ 6 ]
収集家は、移動型か非移動型かという違いだけでなく、収集サイクルにおいて白、グレー、黒のオブジェクトセットをどのように扱うかによっても分類できる。
最も単純なアプローチは、1969年に開発されたセミスペースコレクタです。このムービングコレクタでは、メモリは「from space」と「to space」という同じサイズの領域に分割されます。最初は、「to space」がいっぱいになるまでオブジェクトが割り当てられ、その後コレクションサイクルが開始されます。サイクルの開始時に、「to space」が「from space」になり、逆もまた同様です。ルートセットから到達可能なオブジェクトは、「from space」から「to space」にコピーされます。これらのオブジェクトは順番にスキャンされ、それらが指すすべてのオブジェクトが「to space」にコピーされます。到達可能なすべてのオブジェクトが「to space」にコピーされるまでこのプロセスが繰り返されます。プログラムの実行が再開されると、再び「to space」がいっぱいになるまで新しいオブジェクトが割り当てられ、このプロセスが繰り返されます。
この手法は非常にシンプルですが、オブジェクトの割り当てにセミスペースを1つしか使用しないため、メモリ使用量は他のアルゴリズムの2倍になります。この手法はストップ・アンド・コピーとも呼ばれています。チェイニーのアルゴリズムは、セミスペースコレクタを改良したものです。
マークアンドスイープ方式のガベージコレクタは、各オブジェクトに1ビットまたは2ビットを保持し、それが白か黒かを記録します。グレーセットは別のリストとして、または別のビットを使用して保持されます。コレクションサイクル(「マーク」フェーズ)中に参照ツリーが走査されると、コレクタによってこれらのビットが操作されます。その後、メモリ領域の最終的な「スイープ」によって、白いオブジェクトが解放されます。マークアンドスイープ方式の利点は、廃棄対象セットが決定されたら、移動型または非移動型のコレクション戦略のどちらでも実行できることです。この戦略の選択は、使用可能なメモリに応じて実行時に行うことができます。欠点は、リスト/追加ビットのために、すべてのオブジェクトにわずかな隠れたメモリコストが発生するため、オブジェクトがわずかに「肥大化」することです。コレクタが割り当ても処理する場合は、割り当てデータ構造内の未使用ビットを使用できる可能性があるため、この欠点はある程度軽減できます。または、タグ付きポインタを使用することで、メモリコストをCPU時間と交換して、この「隠れたメモリ」を排除することもできます。しかし、マーク・アンド・スイープは、そもそも外部のアロケーターと容易に協力できる唯一の戦略である。
マークアンドスイープと同様に、マークアンドスイープガベージコレクタは、各オブジェクトに、それが白か黒かを記録するビットを保持します。グレーセットは、別のリストとして、または別のビットを使用して保持されます。ここで重要な違いが 2 つあります。まず、黒と白は、マークアンドスイープコレクタとは異なる意味を持ちます。「マークアンドスイープ」コレクタでは、到達可能なオブジェクトはすべて常に黒です。オブジェクトは割り当て時に黒としてマークされ、到達不能になっても黒のままです。白のオブジェクトは未使用のメモリであり、割り当てることができます。次に、黒/白ビットの解釈が変わる可能性があります。最初は、黒/白ビットは (0=白、1=黒) の意味を持つ場合があります。割り当て操作で使用可能な (白) メモリが見つからない場合、すべてのオブジェクトが使用済み (黒) としてマークされます。すると、黒/白ビットの意味が反転します (たとえば、0=黒、1=白)。すべてが白になります。これにより、到達可能なオブジェクトが黒色であるという不変条件が一時的に破られますが、すぐに完全なマーキングフェーズが実行され、再び黒色にマークされます。これが完了すると、到達不可能なメモリはすべて白色になります。「スイープ」フェーズは不要です。
マークアンドドントスイープ戦略は、アロケータとコレクタの連携を必要としますが、割り当てられたポインタごとに1ビットしか必要としないため(ほとんどの割り当てアルゴリズムはいずれにせよ1ビットしか必要としない)、非常にスペース効率に優れています。しかし、メモリの大部分が誤って黒色(使用済み)としてマークされてしまうため、メモリ使用量が少ないときにシステムにリソースを返還することが難しくなり、この利点はいくらか相殺されます(他のアロケータ、スレッド、またはプロセスが使用するために)。
したがって、マークして掃き掃除をしない戦略は、マークして掃き掃除をする戦略と、停止してコピーする戦略の長所と短所の間の妥協点と見なすことができる。
多くのプログラムにおいて、最も最近作成されたオブジェクトは、すぐにアクセス不能になる可能性が最も高いことが経験的に観察されています(これは「初期死亡率」または「世代仮説」として知られています)。世代別ガベージコレクション(一時的ガベージコレクションとも呼ばれます)は、オブジェクトを世代に分割し、ほとんどのサイクルで、世代のサブセットのオブジェクトのみを初期のホワイトセット(破棄対象)に配置します。さらに、ランタイムシステムは、参照の作成と上書きを監視することで、参照が世代をまたぐタイミングを把握しています。ガベージコレクタが実行される際、この知識を利用して、参照ツリー全体を走査することなく、初期のホワイトセット内の一部のオブジェクトがアクセス不能であることを証明できる場合があります。世代仮説が成り立つ場合、これにより、ほとんどのアクセス不能オブジェクトを回収しながら、コレクションサイクルを大幅に高速化できます。
この概念を実現するために、多くの世代別ガベージコレクタは、オブジェクトの異なる年代ごとに別々のメモリ領域を使用します。領域がいっぱいになると、その領域内のオブジェクトが、古い世代の参照をルートとして使用してトレースされます。通常、この結果、その世代のほとんどのオブジェクトがガベージコレクションされ(仮説による)、その領域は新しいオブジェクトの割り当てに使用できるようになります。コレクションで多くのオブジェクトが収集されない場合(例えば、プログラムが保持したい新しいオブジェクトの大規模なコレクションを計算したため、仮説が成り立たない場合)、古いメモリ領域から参照されている残存オブジェクトの一部またはすべてが次の上位の領域に昇格され、その後、領域全体が新しいオブジェクトで上書きされます。この手法により、一度に1つの領域のガベージコレクションのみで済むため、非常に高速な増分ガベージコレクションが可能になります。
ウンガーの古典的な世代スカベンジャーは2つの世代から構成されます。最も若い世代は「新空間」と呼ばれ、新しいオブジェクトが作成される大きな「エデン」と、過去生存空間および未来生存空間という2つの小さな「生存空間」に分けられます。新空間のオブジェクトを参照する可能性のある古い世代のオブジェクトは「記憶セット」に保持されます。各スカベンジでは、新空間のオブジェクトは記憶セットのルートからトレースされ、未来生存空間にコピーされます。未来生存空間がいっぱいになると、収まらないオブジェクトは旧空間に昇格され、このプロセスは「テニュアリング」と呼ばれます。スカベンジの終了時には、未来生存空間にいくつかのオブジェクトが存在し、エデンと過去生存空間は空になります。その後、未来生存空間と過去生存空間が交換され、プログラムはエデンにオブジェクトを割り当てながら続行されます。ウンガーのオリジナルシステムでは、エデンは各生存空間の5倍の大きさです。
世代別ガベージコレクションはヒューリスティックなアプローチであり、到達不能なオブジェクトは各サイクルで解放されない場合があります。そのため、利用可能なすべての領域を解放するために、完全なマークアンドスイープまたはコピーによるガベージコレクションを実行する必要が生じる場合があります。実際、Javaや.NET Frameworkなどの最新のプログラミング言語のランタイムシステムでは、これまで説明してきたさまざまな戦略を組み合わせたハイブリッド方式が一般的に採用されています。たとえば、ほとんどのコレクションサイクルでは数世代のみを対象とし、時折マークアンドスイープが実行され、さらにまれに断片化対策として完全なコピーが実行されます。「マイナーサイクル」と「メジャーサイクル」という用語は、これらの異なるレベルのコレクターの積極性を表すために使用されることがあります。
単純なストップ・ザ・ワールド型のガベージコレクタは、プログラムの実行を完全に停止させてコレクションサイクルを実行するため、コレクタの実行中に新しいオブジェクトが割り当てられたり、オブジェクトが突然アクセス不能になったりすることがないことを保証します。
この方式の欠点は、ガベージコレクションサイクルが実行中はプログラムが有用な処理を実行できないこと(いわゆる「恥ずかしい一時停止」[ 7 ])です。そのため、ストップ・ザ・ワールド・ガベージコレクションは主に非対話型プログラムに適しています。利点は、インクリメンタル・ガベージコレクションよりも実装が簡単で高速であることです。
インクリメンタル型およびコンカレント型のガベージコレクタは、メインプログラムのアクティビティと交互に処理を行うことで、この中断を軽減するように設計されています。インクリメンタル型ガベージコレクタは、ガベージコレクションサイクルを個別のフェーズで実行し、各フェーズ間(場合によってはフェーズ中にも)プログラムの実行を許可します。コンカレント型ガベージコレクタは、プログラムの実行スタックをスキャンする時以外は、プログラムの実行を一切停止しません。ただし、インクリメンタル型フェーズの合計は、バッチ型ガベージコレクションの1回のパスよりも時間がかかるため、これらのガベージコレクタは、全体のスループットが低くなる可能性があります。
これらの手法を用いる際には、メインプログラムがガベージコレクタに干渉したり、その逆の干渉を起こさないように、慎重な設計が必要です。例えば、プログラムが新しいオブジェクトを割り当てる必要がある場合、ランタイムシステムは、コレクションサイクルが完了するまでプログラムを一時停止するか、あるいは何らかの方法でガベージコレクタに新しい到達可能なオブジェクトが存在することを通知する必要があります。
オブジェクト内のすべてのポインタ(参照)を正しく識別できるコレクタもあります。これらは精密コレクタ(または正確コレクタ)と呼ばれ、その反対は保守的コレクタまたは部分保守的コレクタです。保守的コレクタは、メモリ内の任意のビットパターンが、ポインタとして解釈された場合に割り当てられたオブジェクトを指すのであれば、ポインタである可能性があると想定します。保守的コレクタは、ポインタの識別が不適切なために未使用のメモリが解放されないという誤検出(偽陽性)を生成する可能性があります。プログラムがポインタとして誤識別されやすい大量のデータを処理しない限り、これは実際には必ずしも問題になりません。64ビットシステムでは、有効なメモリ アドレスの範囲が64ビット値の範囲のごく一部であるため、 32ビットシステムよりも誤検出の問題は一般的に少なくなります。したがって、任意の64ビット パターンが有効なポインタを模倣する可能性は低いでしょう。ポインタが「隠蔽」されている場合(たとえば、XORリンク リストを使用する場合)には、偽陰性(偽陰性)が発生することもあります。精密コレクタが実用的かどうかは、通常、対象となるプログラミング言語の型安全性の特性に依存します。保守的なガベージコレクタが必要となる例として、C言語が挙げられます。C言語では、型付き(非void)ポインタを型なし(void)ポインタに型変換したり、その逆を行ったりすることができます。
関連する問題として、内部ポインタ、つまりオブジェクト内のフィールドへのポインタが挙げられます。言語のセマンティクスが内部ポインタを許容する場合、同じオブジェクトの一部を参照するアドレスが複数存在する可能性があり、オブジェクトがガベージであるかどうかを判断するのが複雑になります。その一例として、多重継承によって基底オブジェクトへのポインタのアドレスが異なる場合があるC++言語が挙げられます。高度に最適化されたプログラムでは、オブジェクト自体への対応するポインタがレジスタ内で上書きされている可能性があるため、このような内部ポインタをスキャンする必要があります。
トレース型ガベージコレクタのパフォーマンス(レイテンシとスループットの両方)は、実装、ワークロード、および環境に大きく依存します。単純な実装や、組み込みシステムなどメモリ容量が非常に限られた環境での使用は、他の方法と比較してパフォーマンスが著しく低下する可能性があります。一方、高度な実装や十分なメモリ容量を持つ環境での使用は、優れたパフォーマンスを実現します。
スループットの観点から見ると、トレースはその性質上、暗黙の実行時オーバーヘッドを必要としますが、場合によっては償却コストが非常に低くなり、場合によっては割り当てまたは収集ごとに 1 命令よりも低くなり、スタック割り当てよりも優れたパフォーマンスを発揮します。[ 8 ]手動メモリ管理では、メモリを明示的に解放するためオーバーヘッドが必要となり、参照カウントでは、参照カウントの増減や、カウントがオーバーフローしたかゼロになったかのチェックによるオーバーヘッドが発生します。
レイテンシの観点から見ると、単純なストップ・ザ・ワールド型のガベージコレクタは、ガベージコレクションのためにプログラムの実行を一時停止しますが、これは任意のタイミングで発生し、任意の長さまでかかる可能性があるため、リアルタイムコンピューティング、特に組み込みシステムには適さず、対話型の使用や、低レイテンシが優先されるその他の状況にも不向きです。しかし、インクリメンタルガベージコレクタはハードリアルタイム保証を提供でき、パーソナルコンピュータのようにアイドル時間が頻繁に発生し、十分な空きメモリがあるシステムでは、ガベージコレクションをアイドル時間にスケジュールできるため、対話型パフォーマンスへの影響は最小限に抑えられます。手動メモリ管理(C++など)や参照カウントにも、大きなデータ構造とそのすべての子要素を解放する場合に任意の長さの一時停止が発生するという同様の問題がありますが、これらはガベージコレクションとは関係なく、固定されたタイミングでのみ発生します。
状況によって動作が異なるため、2 つのケースを直接比較することは困難です。たとえば、ガベージコレクションシステムの場合、割り当てはポインタをインクリメントするだけですが、手動ヒープ割り当ての場合、アロケータは特定のサイズのフリーリストを保持し、割り当てにはポインタをたどるだけで済みます。ただし、このサイズ分離は通常、外部断片化の度合いを大きくし、キャッシュの動作に悪影響を与える可能性があります。ガベージコレクション言語でのメモリ割り当ては、(単にポインタをインクリメントするのではなく)内部でヒープ割り当てを使用して実装されている場合があるため、上記のパフォーマンス上の利点は必ずしもこのケースには当てはまりません。組み込みシステムなど、一部の状況では、メモリプールを事前割り当てし、割り当て/解放にカスタムの軽量スキームを使用することで、ガベージコレクションとヒープ管理の両方のオーバーヘッドを回避できます。[ 9 ]
書き込みバリアのオーバーヘッドは、既存のデータ構造にポインタを頻繁に書き込む命令型プログラムでは、データを一度だけ構築して変更しない関数型プログラムよりも顕著になる可能性が高い。
ガベージコレクションの進歩の中には、パフォーマンスの問題への対応として理解できるものもあります。初期のコレクタはストップ・ザ・ワールド方式でしたが、この方式のパフォーマンスは対話型アプリケーションでは邪魔になるという問題がありました。インクリメンタルコレクションはこの邪魔を回避しましたが、バリアが必要となるため効率が低下するという代償を伴いました。世代別コレクション技術は、ストップ・ザ・ワールド方式とインクリメンタル方式の両方でパフォーマンス向上に用いられますが、その代償として、一部のガベージが通常よりも長くガベージとして検出されないという問題が生じます。
ガベージコレクションは一般的に非決定論的ですが、ハードリアルタイムシステムで使用することは可能です。リアルタイムガベージコレクタは、最悪の場合でも、一定数の計算リソースをミューテータースレッドに割り当てることを保証する必要があります。リアルタイムガベージコレクタに課される制約は、通常、作業ベースまたは時間ベースのいずれかです。時間ベースの制約は、次のようになります。各時間ウィンドウ内で、期間ごとに、ミューテーター スレッドは少なくとも次の時間実行できるようにする必要があります時間。作業ベースの分析では、MMU(最小ミューテーター利用率)[ 10 ]が通常、ガベージコレクションアルゴリズムのリアルタイム制約として使用されます。
JVMのハードリアルタイムガベージコレクションの最初の実装の 1 つは、Metronome アルゴリズムに基づいています[ 11 ]。その商用実装は、IBM WebSphere Real Timeの一部として利用可能です[ 12 ]。もう 1 つのハードリアルタイムガベージコレクションアルゴリズムは Staccato で、IBMのJ9 JVMで利用可能です。これは、大規模なマルチプロセッサアーキテクチャへのスケーラビリティも提供し、Metronome や他のアルゴリズムとは異なり、専用のハードウェアを必要とするさまざまな利点をもたらします[ 13 ] 。
最新のマルチコアアーキテクチャにおけるリアルタイムガベージコレクションの大きな課題の1つは、並行スレッドが互いにブロックし合って予測不可能な一時停止が発生しないように、ノンブロッキング並行ガベージコレクションを設計することです。ノンブロッキングリアルタイム並行ガベージコレクションを可能にするアルゴリズムの研究は、Microsoft ResearchのPizloらの論文に掲載されています。[ 14 ]