垃圾收集器的代数没有递增

时间:2016-01-02 18:29:46

标签: c# .net garbage-collection

我对垃圾收集过程有很多疑问,主要是它何时运行,何时将对象设置为老一代,等等......

static void Main(string[] args)
{
    int i = 0, j = 0; 
    int a = 0;
    Holder prev = new Holder(null);

    while(GC.CollectionCount(1) == 0)
    {
        int aux = GC.CollectionCount(0);
        if(aux > a){
            a = aux; 
            ++j; 
            Console.WriteLine((i+1));
         }
        ++i;
        Holder h = new Holder(prev);
        Console.WriteLine(GC.GetGeneration(prev));
        prev = h;
    }
}

我正在尝试获取gen1中的对象数量。 为什么j = 1; ?? GC只在gen0上运行一次(暂时不应该至少运行2次)?

[编辑] 通过在休息之后添加这个,我非常困惑

Console.WriteLine("#gc0 = "+GC.CollectionCount(0)); --> 2 Console.WriteLine("#gc1 = "+GC.CollectionCount(1)); --> 1 Console.WriteLine("#objs = "+ i); Console.ReadLine();

为什么GC.CollectionCount(0)只有2?我一直在通过c#阅读Richter clr,他说这个

  

检查第1代中的对象   只有当第1代达到预算时,通常需要几次垃圾收集   第0代。

[编辑]

但与此同时,如果gc看到所有对象都存活了,它会增加g0限制,也许是g0上只有2 gc的原因?

1 个答案:

答案 0 :(得分:1)

我们如何用这样的随机性来调味:

    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random();

            int i = 0, j = 0;
            int a = 0;
            Holder prev = new Holder(null);
            Holder prev2 = new Holder(null);

            while (GC.CollectionCount(1) == 0)
            {
                int aux = GC.CollectionCount(0);
                if (aux > a)
                {
                    a = aux;
                    ++j;
                    Console.WriteLine((i + 1));
                }
                ++i;
                var flag = random.Next(1) == 1;
                Holder h = new Holder(flag ? prev : prev2);
                Console.WriteLine("Prev: " + GC.GetGeneration(prev));
                Console.WriteLine("Prev2: " + GC.GetGeneration(prev2));

                if (flag)
                {
                    prev = h;
                }
                else
                {
                    prev2 = h;
                }
            }
        }
    }

    internal class Holder
    {
        private Holder holder;

        public Holder(Holder o)
        {
            holder = o;
        }
    }

您提供的代码示例非常简单,以至于CLR知道将prev项移动到另一代并没有意义。 它的使用很简单,我认为运行时已将它优化为只能在G0上运行。

添加更复杂的逻辑会破坏运行时的优化,现在prevprev1中的一个会进入G1,具体取决于较少使用的对象(不知道确切的机制)这里)。

您可以尝试添加代替prevprev2 prevs数组,并在索引上随机执行,您可以更好地了解数组元素如何推进世代。