Criteria for starting garbage collection in .Net

I met some curious behavior regarding garbage collection in .Net.

The following program will quickly throw an OutOfMemoryException (in less than a second on a 2-bit 32-bit machine). The Foo finalizer is never called.

class Foo { Guid guid = Guid.NewGuid(); byte[] buffer = new byte[1000000]; static Random rand = new Random(); public Foo() { // Uncomment the following line and the program will run forever. // rand.NextBytes(buffer); } ~Foo() { // This finalizer is never called unless the rand.NextBytes // line in the constructor is uncommented. } static public void Main(string args[]) { for (; ; ) { new Foo(); } } } 

If the string rand.nextBytes is uncommented, it will run indefinitely, and the Foo finalizer will be called regularly. Why is this?

My best guess is that in the first case, CLR or Windows VMM are lazy in allocating physical memory. The buffer is never written, so physical memory is never used. When the address space ends, the system crashes. In the latter case, the system runs out of physical memory, before it leaves the address space, the GC starts up and objects are collected.

However, here is the part that I am not getting. Assuming my theory is correct, why doesn't the GC start when the address space is running low? If my theory is wrong, then what is the true explanation?

+6
garbage-collection clr
source share
1 answer

The code runs on a stable 18 MB on my machine with or without this line (XP SP3 x86, .Net 3.5 SP1, dual core).

What is likely happening on your machine is that when a line is commented out, the program spends most of its time allocating and manages to allocate too much memory before the garbage collector thread has a chance to free it. When you uncomment this line, the program spends much less time distributing and, therefore, cannot allocate too much before starting the GC thread.

Try replacing the commented line with Thread.Sleep(0) ; if it doesn't fall, I'm probably right.


As a note, you should never rely on a finalizer - it cannot be called immediately when a GC'ed object or even at all. Instead, they implement the IDisposable interface in real code and use the finalizer only if it is extremely important to call Dispose() , even if the programmer forgot it (for example, freeing shared network / file resources, etc.)

+1
source share

All Articles