C# Language
Garbage Collector in .Net
Zoeken…
Verdichting van grote objecten
Standaard is de Large Object Heap niet gecomprimeerd in tegenstelling tot de klassieke Object Heap die kan leiden tot geheugenfragmentatie en verder kan leiden tot OutOfMemoryException
s
Vanaf .NET 4.5.1 is er een optie om de Large Object Heap expliciet te comprimeren (samen met een afvalinzameling):
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
Net als elk expliciet verzoek voor het ophalen van afval (het wordt verzoek genoemd omdat de CLR dit niet moet uitvoeren) voorzichtig gebruiken en dit standaard vermijden, omdat het GC
statistieken kan de-kalibreren, waardoor de prestaties afnemen.
Zwakke referenties
In .NET wijst de GC objecten toe wanneer er geen verwijzingen meer naar zijn. Daarom, hoewel een object nog steeds kan worden bereikt vanuit code (er is een sterke verwijzing naar), zal de GC dit object niet toewijzen. Dit kan een probleem worden als er veel grote objecten zijn.
Een zwakke referentie is een referentie waarmee de GC het object kan verzamelen en toch toegang tot het object kan krijgen. Een zwakke referentie is alleen geldig gedurende de onbepaalde tijd totdat het object wordt verzameld wanneer er geen sterke referenties bestaan. Wanneer u een zwakke referentie gebruikt, kan de toepassing nog steeds een sterke referentie naar het object verkrijgen, waardoor wordt voorkomen dat het wordt verzameld. Dus zwakke referenties kunnen nuttig zijn voor het vasthouden aan grote objecten die duur zijn om te initialiseren, maar die beschikbaar moeten zijn voor afvalinzameling als ze niet actief in gebruik zijn.
Eenvoudig gebruik:
WeakReference reference = new WeakReference(new object(), false);
GC.Collect();
object target = reference.Target;
if (target != null)
DoSomething(target);
Dus zwakke referenties kunnen worden gebruikt om bijvoorbeeld een cache van objecten bij te houden. Het is echter belangrijk om te onthouden dat er altijd het risico is dat de vuilnisman het object bereikt voordat een sterke referentie wordt hersteld.
Zwakke referenties zijn ook handig om geheugenlekken te voorkomen. Een typisch gebruik is bij evenementen.
Stel dat we een handler hebben voor een evenement op een bron:
Source.Event += new EventHandler(Handler)
Deze code registreert een gebeurtenishandler en creëert een sterke verwijzing van de gebeurtenisbron naar het luisterobject. Als het bronobject een langere levensduur heeft dan de luisteraar en de luisteraar de gebeurtenis niet meer nodig heeft wanneer er geen andere verwijzingen naar zijn, veroorzaakt het gebruik van normale .NET-gebeurtenissen een geheugenlek: het bronobject houdt luisteraarobjecten in het geheugen vast die moet afval worden verzameld.
In dit geval kan het een goed idee zijn om het patroon voor zwakke gebeurtenissen te gebruiken.
Zoiets als:
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);
}
}
en zo gebruikt:
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); });
In dit geval hebben we natuurlijk enkele beperkingen - het evenement moet een zijn
public event EventHandler<SomeEventArgs> Event;
Zoals MSDN suggereert:
- Gebruik lange zwakke referenties alleen wanneer dat nodig is, omdat de status van het object na het voltooien onvoorspelbaar is.
- Gebruik geen zwakke verwijzingen naar kleine objecten, omdat de aanwijzer zelf even groot of groter kan zijn.
- Gebruik geen zwakke referenties als automatische oplossing voor problemen met geheugenbeheer. In plaats daarvan ontwikkelt u een effectief cachingbeleid voor het verwerken van de objecten van uw toepassing.