En mi trabajo tuvimos un problema con OutOfMemoryExceptions. Escribí un código simple para imitar algún comportamiento, y terminé con el siguiente misterio. Mira este código simple que explota cuando se queda sin memoria..NET Garbage Collector mystery
class Program
{
private static void Main()
{
List<byte[]> list = new List<byte[]>(200000);
int iter = 0;
try
{
for (;;iter++)
{
list.Add(new byte[10000]);
}
}
catch (OutOfMemoryException)
{
Console.WriteLine("Iterations: " + iter);
}
}
}
En mi máquina terminó con
Iterations: 148008
Luego he añadido una llamada GC.Collect
al bucle después de cada mil iteraciones:
//...
for (;;iter++)
{
list.Add(new byte[10000]);
if (iter % 1000 == 0)
GC.Collect();
}
//...
y sorpresa:
Iterations: 172048
Cuando llamé a GC.Collect
después de cada 10 iteraciones, incluso obtuve 193716 ciclos. Hay dos cosas extrañas:
¿Cómo puede una llamada manual para
GC.Collect
tener un impacto tan grave (hasta un 30% más asignó)?¿Qué demonios puede recolectar GC, cuando no hay referencias "perdidas" (incluso preestablecí la capacidad de la Lista)?
Pregunta interesante. Supongo que tiene que ver con la desfragmentación del espacio de memoria, y si llama a GC. Recolecte lo suficiente para mantener el bloque contiguo más grande, de modo que la excepción se produzca más tarde. Pero eso es solo una suposición descabellada y estoy esperando a ver lo que otros tienen que decir. – Lucero
No puedo responder la pregunta, pero en 2) no puede indicar que no hay referencias perdidas porque no puede ver el método "Agregar". – flq
@Frank: Es un punto justo, pero he intentado lo mismo con una matriz simple y el resultado fue el mismo. – Elephantik