C# Language
Recolector de basura en .Net
Buscar..
Compactación de objetos grandes
De forma predeterminada, el Large Object Heap no se compacta a diferencia del Object Heap clásico, que puede conducir a la fragmentación de la memoria y, además, puede llevar a OutOfMemoryException
s
A partir de .NET 4.5.1, hay una opción para compactar explícitamente el montón de objetos grandes (junto con una recolección de basura):
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
Al igual que cualquier solicitud de recolección de basura explícita (se llama solicitud porque el CLR no está obligado a realizarla), utilice con cuidado y evítelo de manera predeterminada si puede, ya que puede GC
las estadísticas de GC
, lo que disminuye su rendimiento.
Referencias débiles
En .NET, el GC asigna objetos cuando no hay referencias a ellos. Por lo tanto, si bien se puede acceder a un objeto desde el código (hay una fuerte referencia a él), el GC no asignará este objeto. Esto puede convertirse en un problema si hay muchos objetos grandes.
Una referencia débil es una referencia, que le permite al GC recolectar el objeto y al mismo tiempo permitir el acceso al objeto. Una referencia débil solo es válida durante un período de tiempo indeterminado hasta que el objeto se recopila cuando no existen referencias sólidas. Cuando utiliza una referencia débil, la aplicación aún puede obtener una referencia fuerte al objeto, lo que evita que se recopile. Por lo tanto, las referencias débiles pueden ser útiles para aferrar objetos grandes que son costosos de inicializar, pero deberían estar disponibles para la recolección de basura si no están en uso.
Uso simple:
WeakReference reference = new WeakReference(new object(), false);
GC.Collect();
object target = reference.Target;
if (target != null)
DoSomething(target);
Por lo tanto, las referencias débiles podrían usarse para mantener, por ejemplo, un caché de objetos. Sin embargo, es importante recordar que siempre existe el riesgo de que el recolector de basura llegue al objeto antes de que se restablezca una referencia sólida.
Las referencias débiles también son útiles para evitar pérdidas de memoria. Un caso de uso típico es con eventos.
Supongamos que tenemos algún controlador para un evento en una fuente:
Source.Event += new EventHandler(Handler)
Este código registra un controlador de eventos y crea una fuerte referencia desde el origen del evento hasta el objeto que escucha. Si el objeto de origen tiene una vida útil más larga que la del oyente, y el oyente ya no necesita el evento cuando no hay otras referencias a él, el hecho de que los eventos .NET normales provoquen una pérdida de memoria: el objeto de origen guarda los objetos del oyente en la memoria. Se debe recoger la basura.
En este caso, puede ser una buena idea usar el Patrón de evento débil .
Algo como:
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);
}
}
y usado así:
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); });
En este caso, por supuesto, tenemos algunas restricciones: el evento debe ser un
public event EventHandler<SomeEventArgs> Event;
Como sugiere MSDN :
- Utilice referencias débiles largas solo cuando sea necesario, ya que el estado del objeto es impredecible después de la finalización.
- Evite usar referencias débiles para objetos pequeños porque el puntero en sí puede ser tan grande o más grande.
- Evite utilizar referencias débiles como una solución automática a los problemas de administración de memoria. En su lugar, desarrolle una política de almacenamiento en caché eficaz para manejar los objetos de su aplicación.