I wrote a small Console app experiment:
static void Main()
{
int GetTotalCollections()
{
var total = 0;
for (var generation = 0; generation <= GC.MaxGeneration; generation++)
total += GC.CollectionCount(generation);
return total;
}
CreateGarbage();
WriteLine("Number of collections occurred: {0}", GetTotalCollections());
}
static void CreateGarbage()
{
WriteLine(new object().GetHashCode());
WriteLine(new object().GetHashCode());
WriteLine(new object().GetHashCode());
ReadKey();
}
When I run it in Release
mode without the debugger attached, I get 0
collections for all the generations.
As it seemed weird, I attached WinDbg
to the process and !dumpheap -live
does not show the objects whereas !dumpheap
does. Unfortunately -live
is not part of the official documentation for SOS, but I was assuming it showed only uncollected objects.
Is the GC
collecting and not reporting it (as it should be in this scenario) or have I misunderstood the !dumpheap -live
output? (maybe showing only object with a GC root
?)
If I allocate more objects to be sure I trigger a collection (or invoke GC.Collect
) I get a collection count increase, but still the same output in WinDbg:
static void GetValue()
{
for (var i = 0; i < 1000000; i++)
new object();
ReadKey();
}
EDIT: The last sentence was an oversight (which caused the confusion), if I force the collection, !dumpheap -stat
does not show the objects any more as expected (I just forgot to run the app from WinDbg
before pressing a key to force the collection.)
!dumpheap -stat
shows uncollected objects both live and dead and !dumpheap -stat -live
shows only objects with a GC root
as @Thomas answered. Once collected they disappear from the output of all the commands.