Recherche…


Compactage de tas de gros objets

Par défaut, le tas d'objets volumineux n'est pas compacté, contrairement au segment d'objets classique, ce qui peut entraîner une fragmentation de la mémoire et entraîner une OutOfMemoryException s.

À partir de .NET 4.5.1, il existe une option permettant de compacter explicitement le tas de grands objets (avec un ramasse-miettes):

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();   

Tout comme toute demande explicite de récupération de place (appelée requête parce que le CLR n’est pas obligé de le faire), utiliser avec précaution et par défaut l’éviter si possible, car elle peut dé-calibrer les statistiques du GC , en réduisant ses performances.

Références faibles

Dans .NET, le GC alloue des objets lorsqu'il ne leur reste aucune référence. Par conséquent, même si un objet peut toujours être atteint à partir du code (il y a une référence forte), le GC n'allouera pas cet objet. Cela peut devenir un problème s'il y a beaucoup de gros objets.

Une référence faible est une référence qui permet au GC de collecter l'objet tout en permettant d'accéder à l'objet. Une référence faible n'est valide que pendant la durée indéterminée jusqu'à ce que l'objet soit collecté en l'absence de références fortes. Lorsque vous utilisez une référence faible, l'application peut toujours obtenir une référence forte à l'objet, ce qui l'empêche d'être collecté. Les références faibles peuvent donc être utiles pour conserver des objets volumineux dont l’initialisation est coûteuse, mais qui doivent être disponibles pour la récupération de mémoire s’ils ne sont pas activement utilisés.

Utilisation simple:

WeakReference reference = new WeakReference(new object(), false);

GC.Collect();

object target = reference.Target;
if (target != null)
  DoSomething(target);

Des références faibles pourraient donc être utilisées pour conserver, par exemple, un cache d'objets. Cependant, il est important de garder à l'esprit qu'il existe toujours le risque que le garbage collector atteigne l'objet avant qu'une référence forte ne soit rétablie.

Les références faibles sont également utiles pour éviter les fuites de mémoire. Un cas d'utilisation typique concerne les événements.

Supposons que nous ayons un gestionnaire pour un événement sur une source:

Source.Event += new EventHandler(Handler)

Ce code enregistre un gestionnaire d'événement et crée une référence forte de la source d'événement à l'objet d'écoute. Si l'objet source a une durée de vie plus longue que l'écouteur et que l'écouteur n'a plus besoin de l'événement lorsqu'il n'y a pas d'autres références, l'utilisation d'événements .NET normaux provoque une fuite de mémoire: l'objet source contient des objets d'écouteur en mémoire devrait être ramassé des ordures.

Dans ce cas, il peut être utile d'utiliser le modèle d'événement faible .

Quelque chose comme:

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);
        }
    }

et utilisé comme ceci:

 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); });

Dans ce cas, bien sûr, nous avons des restrictions - l’événement doit être un

public event EventHandler<SomeEventArgs> Event;

Comme MSDN le suggère:

  • Utilisez des références longues et faibles uniquement lorsque cela est nécessaire, car l'état de l'objet est imprévisible après la finalisation.
  • Évitez d'utiliser des références faibles à de petits objets, car le pointeur lui-même peut être plus grand ou plus grand.
  • Évitez d'utiliser des références faibles comme solution automatique aux problèmes de gestion de la mémoire. Au lieu de cela, développez une stratégie de mise en cache efficace pour gérer les objets de votre application.


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow