C# Language
.NETのガベージコレクタ
サーチ…
ラージオブジェクトヒープ圧縮
デフォルトでは、ラージオブジェクトヒープは、メモリの断片化につながる可能性のある従来のオブジェクトヒープとは異なり、 OutOfMemoryException
つながる可能性があります
.NET 4.5.1以降、ラージオブジェクトヒープを(ガベージコレクションと共に)明示的に圧縮するオプションがあります 。
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
明示的なガーベジコレクション要求(CLRが強制的に実行されないためリクエストと呼ばれます)と同じように注意して使用してください。デフォルトでGC
の統計をデキャリブレートしてパフォーマンスを低下させる可能性があるので避けてください。
弱い参照
.NETでは、GCは参照が残っていないときにオブジェクトを割り当てます。したがって、コードからオブジェクトに到達することはできますが(強い参照があります)、GCはこのオブジェクトを割り当てません。大きなオブジェクトがたくさんある場合、これは問題になる可能性があります。
ウィークリファレンスは参照であり、オブジェクトにアクセスできるようにしながらGCがオブジェクトを収集できるようにします。弱参照は、強い参照が存在しないときにオブジェクトが収集されるまで不確定な時間中にのみ有効です。ウィークリファレンスを使用すると、アプリケーションは引き続きオブジェクトへの強い参照を取得することができ、オブジェクトの収集が妨げられます。したがって、弱い参照は、初期化するのに費用がかかりますが、積極的に使用されていない場合はガベージコレクションのために利用できるはずの大きなオブジェクトを保持するのに便利です。
簡単な使い方:
WeakReference reference = new WeakReference(new object(), false);
GC.Collect();
object target = reference.Target;
if (target != null)
DoSomething(target);
したがって、例えばオブジェクトのキャッシュを維持するために、弱い参照を使用することができます。ただし、強い参照が再確立される前にガベージコレクタがオブジェクトに到達するリスクは常に存在することを覚えておくことが重要です。
弱い参照はメモリリークを回避するのにも便利です。典型的なユースケースはイベントです。
ソース上のイベントに対するハンドラがあるとします。
Source.Event += new EventHandler(Handler)
このコードはイベントハンドラを登録し、イベントソースからリスニングオブジェクトへの強力な参照を作成します。ソースオブジェクトがリスナーよりも寿命が長く、リスナーに他の参照がないときにリスナーがイベントを必要としない場合、通常の.NETイベントを使用するとメモリリークが発生します。ソースオブジェクトはメモリ内のリスナーオブジェクトを保持します。ガベージコレクションする必要があります。
この場合、 弱いイベントパターンを使用することをお勧めします。
何かのようなもの:
public static class WeakEventManager
{
public static void SetHandler<S, TArgs>(
Action<EventHandler<TArgs>> add,
Action<EventHandler<TArgs>> remove,
S subscriber,
Action<S, TArgs> action)
where TArgs : EventArgs
where S : class
{
var subscrWeakRef = new WeakReference(subscriber);
EventHandler<TArgs> handler = null;
handler = (s, e) =>
{
var subscrStrongRef = subscrWeakRef.Target as S;
if (subscrStrongRef != null)
{
action(subscrStrongRef, e);
}
else
{
remove(handler);
handler = null;
}
};
add(handler);
}
}
このように使用されます:
EventSource s = new EventSource();
Subscriber subscriber = new Subscriber();
WeakEventManager.SetHandler<Subscriber, SomeEventArgs>(a => s.Event += a, r => s.Event -= r, subscriber, (s,e) => { s.HandleEvent(e); });
この場合、いくつかの制限があります。イベントは
public event EventHandler<SomeEventArgs> Event;
MSDNが示唆するように:
- オブジェクトの状態はファイナライズ後に予測できないので、必要に応じて長い弱い参照を使用してください。
- ポインタ自体が大きくても大きくてもかまいませんので、小さなオブジェクトへの弱参照は避けてください。
- メモリ管理の問題に対する自動解決策として弱参照を使用しないでください。代わりに、アプリケーションのオブジェクトを処理するための効果的なキャッシング・ポリシーを作成します。