В моей работе у нас была проблема с OutOfMemoryExceptions. Я написал простой фрагмент кода, чтобы подражать некоторому поведению, и у меня закончилась следующая тайна. Посмотрите на этот простой код, который взрывается, когда заканчивается память.
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);
}
}
}
На моей машине это закончилось с
Iterations: 148008
Затем я добавил вызов GC.Collect
в цикл после каждой тысячи итераций:
//...
for (;;iter++)
{
list.Add(new byte[10000]);
if (iter % 1000 == 0)
GC.Collect();
}
//...
И с удивлением:
Iterations: 172048
Когда я назвал GC.Collect
после каждых 10 итераций, я даже получил 193716 циклов. Есть две странные вещи:
-
Как может ручное обращение к
GC.Collect
иметь такое серьезное воздействие (на 30% больше выделено)? -
Что, черт возьми, может собрать GC, когда нет "потерянных" ссылок (я даже задал емкость списка)?