.NET Garbage Collector mystery

Viewed 1967

In my job we had a problem with OutOfMemoryExceptions. I've written a simple piece of code to mimic some behavior, and I've ended up with the following mystery. Look at this simple code which blows up when it runs out of memory.

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

On my machine it ended up with

Iterations: 148008

Then I added a GC.Collect call to the loop after each thousand iterations:

            //...
            for (;;iter++)
            {
                list.Add(new byte[10000]);

                if (iter % 1000 == 0)
                    GC.Collect();
            }
            //...

And surprise:

Iterations: 172048

When I called GC.Collect after each 10 iterations, I even got 193716 cycles. There are two strange things:

  1. How can a manual call to GC.Collect have such a severe impact (up to 30% more allocated)?

  2. What the hell can GC collect, when there're no "lost" references (I've even preset the List's capacity)?

4 Answers
Related