.Netでのガベージコレクションを容易にするためのベストプラクティス

Microsoft.Netでは、ガベージコレクションは、アプリケーションによって消費されるリソースをクリーンアップするために共通言語ランタイム(CLR)によって採用されるメカニズムです。.Netでオブジェクトを作成すると、それらはマネージヒープに格納されます。オブジェクトを作成する必要がありますが、ほとんどの場合、オブジェクトのクリーンアップについて心配する必要はありません。ランタイムがそれを行います。

ただし、ガベージコレクションを容易にし、リソースをより迅速にクリーンアップできるように、アプリケーションでベストプラクティスを採用する必要があります。.Netは管理対象オブジェクトの再利用に長けていますが、アプリケーションのパフォーマンスを向上させるために、ガベージコレクションを高速化するために特定のガイドラインに従う必要があります。この記事では、ガベージコレクションがどのように機能するか、および.Netでのガベージコレクションを容易にするためのベストプラクティスについて説明します。

ガベージコレクションはいつ行われますか?

ガベージコレクションは、システムで使用可能な物理メモリが不足している場合、またはGC.Collect()アプリケーションのコードでメソッドが明示的に呼び出されている場合に実行されます。使用されなくなったオブジェクト、またはルートから到達できないオブジェクトは、ガベージコレクションの候補です。本質的に、ガベージコレクタは、参照のないオブジェクトによって占有されているメモリをクリーンアップします。

世代

ランタイムは、マネージヒープを世代に編成します。これらの世代を使用して、短命および長命のオブジェクトを整理します。ガベージコレクターは、上位世代よりも下位世代ではるかに頻繁に機能することに注意してください。ジェネレーション0には、一時オブジェクトなどの短命のオブジェクトが含まれています。オブジェクトが作成されると、大きなオブジェクトでない限り、第0世代に保存されます。オブジェクトがラージオブジェクトの場合、ジェネレーション2のラージオブジェクトヒープ(LOH)に格納されます。ほとんどの場合、ジェネレーション0オブジェクトは、バックグラウンドで実行されるときにガベージコレクターによって再利用されます。

コードを作成するときは、特定のベストプラクティスに従う必要があります。例として、ガベージコレクションを容易にするために、可能な限りローカルスコープにオブジェクトを作成する必要があります。より高いスコープで作成されたオブジェクトは、通常、より長い期間メモリに存在します。CLRプロファイラーを利用して、アプリケーションの割り当てパターンを理解できます。

GC.Collect()すべての世代(世代0、1、および2)の完全なコレクションが発生するため、メソッドの呼び出しは避けてください。GC.Collect()メソッドを呼び出すと、ランタイムはアプリケーション内のすべてのライブオブジェクトにアクセスします。これにはかなりの時間がかかるため、非常にコストのかかる操作になります。結果として、GC.Collect()メソッドを呼び出すことは良い習慣ではありません。

GC.Collect()メソッドを呼び出す必要がある場合は、呼び出しGC.WaitForPendingFinalizers()後にを呼び出しGC.Collect()て、現在実行中のスレッドがすべてのオブジェクトのファイナライザーが実行されるまで待機するようにする必要があります。

次に、GC.Collect()メソッドを再度呼び出して、残っている死んだオブジェクトを確実に収集する必要があります。オブジェクトのファイナライザーメソッドの呼び出しが原因で作成された可能性のあるこれらのデッドオブジェクト。次のコードスニペットは、これらのメソッドの使用方法を示しています。

System.GC.Collect();

System.GC.WaitForPendingFinalizers();

System.GC.Collect();

非表示の割り当てを最小限に抑え、短命のオブジェクトをより高い世代に昇格させる可能性が排除されるようにコードを記述する必要があります。短命のオブジェクトがより高い世代に昇格するのを避けるために、長命のオブジェクトから短命のオブジェクトを参照しないでください。

また、クラスのファイナライザーを作成することは避けてください。クラスにファイナライザーが実装されている場合、ランタイムがファイナライズ可能なオブジェクトを古い世代にプロモートする必要があるため、そのようなクラスのオブジェクトは長寿命のオブジェクトになります。このようなオブジェクトがアプリケーションで必要ない場合は、長時間実行する呼び出しを行う前に、オブジェクトをnullに設定する必要があります。アプリケーションに静的オブジェクトやその他のオブジェクトが不要になった場合は、長時間実行する呼び出しを行う前に、それをnullに設定する必要があります。ローカル変数は不要なので、nullに設定しないでください。ランタイムは、コードで参照されていない、またはそれ以上使用されていないローカルオブジェクトを判別できるため、ローカル変数を明示的にnullに設定する必要はありません。