locked
Garbage Collection - Generations. RRS feed

  • Question

  • I have created a trivial console program that simply creates char arrays into a single variable:

     

    while (true)

    {

       int t = 0;

       char [] dummy = new char[50000];

        for (i=0; i<50000;++i)

             t+= dummyIdea;

        Console.WriteLine(i);

    }

     

    The Console outpuit is wimply to prevent things from being optimized out of existance...

     

    I would expect to see a very high number of Gen-0 collections, and no Gen-1 or Gen-2 collections.

     

    However, using perfmon on this (btw: .Net 2.0), is showing that EVERY (or at least very nearly) collection is a full Gen-2 collection (i.e. the counters for all three are incrementing at the same rate)....

     

    I know I must be missing something, but WHAT?????

     

    Tuesday, May 22, 2007 2:16 PM

Answers

  • I like "wimply" Wink.  At 100,000 bytes for your array, it will be allocated in the Large Object Heap.  The threshold is 85,000 bytes.  They'll be collected during a Generation 2 collection.  I can't find it documented anywhere, but I'd guess the CLR is smart enough to realize it should continue into a Generation 2 collection when a lot of LOH references got collected during a Generation 0 collection.
    Tuesday, May 22, 2007 4:15 PM

All replies

  • I like "wimply" Wink.  At 100,000 bytes for your array, it will be allocated in the Large Object Heap.  The threshold is 85,000 bytes.  They'll be collected during a Generation 2 collection.  I can't find it documented anywhere, but I'd guess the CLR is smart enough to realize it should continue into a Generation 2 collection when a lot of LOH references got collected during a Generation 0 collection.
    Tuesday, May 22, 2007 4:15 PM
  • Here is some explanation from Tess:
    http://blogs.msdn.com/tess/archive/2007/04/10/net-garbage-collector-popquiz-followup.aspx

    6. If you look at the GC sizes for Generation 0, 1 and 2 in perfmon, why is most of the memory in the process in Gen 2?

    As Stefan and others mentioned gen 0 and 1 have fairly small sizes, and once these are reached the objects in there that are still referenced move into Gen 2.  Although the sizes are not "fixed" as Stefan suggests, but rather dynamic over the life of the process, in order to get the most value out of each GC, they are still limited, and objects will only stay there until the next Gen 0/Gen 1 GC as opposed to Gen 2 where referenced objects will stay forever.

    In other words, given a limit x for Gen 0 and y for Gen 1.  The rest of the .NET memory usage (for managed objects) has to be in either Gen 2 or the large object heap. No matter how good your allocation pattern is, there is no way that you can fit say 100 MB in Gen 0 and Gen 1Smile   The trick is just to not let objects spill over to Gen 2 and then die immediately so that you have a lot of turnover in Gen 2. 


    This means bascially that if you allocate "big" objects which are still smaller than the large object heap are directly created as generation 2 objects because they do not fit into the generation 1 and 2 buffers.

    Yours,
       Alois Kraus


    Tuesday, May 22, 2007 9:15 PM
  • SMACK!

     

    I deliberately picked 50,000 to stay off of the LOH, but spaced on the fact that I am dealing with Unicode. I have been working on an embeeded system for the past few weeks.....

     

    Thanks for the Answer. Reducing the Size completely reproduced the behavior I was expecting.

     

     

     

    Wednesday, May 23, 2007 12:16 AM