Reputation: 1975
I have application that is processing large amount of data and I'm monitoring .NET memory performance counters for it. Based on perf counters the #Bytes in All Heaps is slowly growing (about 20MB per 12 hours). All 3 generations are also being collected (gen0 few times per second, gen1 approximately once per second, gen2 approximately once per minute) - but it doesn't prevent the #Bytes in All Heaps from slowly growing. However if I explicitly run:
GC.Collect();
GC.WaitForPendingFinalizers();
It will collect all the extra consumed memory. (e.g. if run after 12 hours, heaps footprint drops by 20MB).
I was also trying to inspect the dump (before running GC.Collect
) by sos and sosex - and majority of object hanging around are unrooted.
Why are not the implicit garbage collection runs (showed by performance counters) collecting the memory, that explicit GC.Collect()
call does?
EDIT:
I forgot to mention that objects that are remaining to hang around unrooted are NOT implementing IDisposable - so they should be reclaimed during the first run of GC on that particular generation (in another words - potential problem with wrong Dispose() method and deadlocked finalizer is out of question here. But points up to Stephen and Roy for pointing to this possibility)
Upvotes: 1
Views: 1478
Reputation: 33139
The garbage collector is actually pretty intelligent. It does not collect memory if it doesn't have to, and that provides it some optimization flexibility.
It keeps open the option of resurrecting the objects that require finalization but that are not yet finalized. As long as the memory is not required, the garbage collector thus does not force the finalization, just in case it can resurrect those objects.
Upvotes: 3