CLR GC的世代预算?

时间:2012-04-08 07:10:51

标签: c# .net-4.0 garbage-collection clr

我有这个简单的代码:

sealed class GenObj
{
    ~GenObj()
    {
        Console.WriteLine("In Finalize method");
    }
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine("Maximum generations: " + GC.MaxGeneration);
        Object o = new GenObj();
        Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 3
        GC.Collect();
        Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 5
        GC.Collect();
        Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 7
        GC.Collect();
        Console.WriteLine("Gen " + GC.GetGeneration(o)); 

    }
}

输出:

Maximum generations: 2
Gen 0
Gen 1
Gen 2
Gen 2

但是有一个问题。

这本书(c#via clr)也在开头说:

  

当CLR初始化时,它会为所有三个选择预算   代。正如我之前提到的,第0代的预算是   约为256 KB,第1代的预算约为2 MB。

     

...

     

可能有几个集合,但是中的对象   第1代仅在第1代达到其预算时进行检查,   这通常需要几代0的垃圾收集。

问题:

在第4行,我可以理解它为什么不在第1代。(在GC之后从0移到1)

我不理解的是第7行。

根据这本书:the objects in generation 1 are examined only when generation 1 reaches its budget

我认为它已经达到预算。所以我想它应该留在第一代!!!

根据这本书 - 它不应该转移到第二代。

我缺少什么?

P.S。这里是link,其中有书中的精确文本(相信我,我有PDF)

4 个答案:

答案 0 :(得分:2)

在向该书的作者发送电子邮件之后

这是他的回答

  

预算用于告诉GC哪些代IT应该   搜集。如果您自己调用GC.Collect,那么您正在告诉GC   忽略预算,只做一个集合。你逼迫了   早期收集,促进老一代的对象。

答案 1 :(得分:1)

我相信Damien是对的。本书描述了当您不强制完全垃圾收集时会发生什么。但你这样做。所以,正确的文字可以是这样的:

  

可能有多个集合,但只有在第1代GC发生时才会检查第1代中的对象。第1代GC发生在第1代达到预算时,通常需要第0代的几个垃圾收集,但您也可以通过调用GC.Collect(1)来强制它。

答案 2 :(得分:1)

不要相信你在书中读到的所有内容。

当作者写这本书时,他/她可能不完全理解这个主题。 在作者写完这本书之后,实施可能已经改变了。

以下是我的理解:

初始GC预算由gc模式和机器配置决定。

小对象在gen0区域中分配,移动到gen1区域,然后通常移动到gen2区域。 大对象分配在大对象堆中,这被认为是gen2。

答案 3 :(得分:0)

以下是测试GC预算的方法:

    const int AllocSize = 64;            // 64 kb block
    const int MaxBudget = 5 * 1024;      // Test max to 5 mb

    static int GetG0Budget()
    {
        GC.Collect(0, GCCollectionMode.Forced, true);

        int gcCount = GC.CollectionCount(0);

        int sum = 0;

        for (int i = 0; i < MaxBudget; i += AllocSize)
        {
            byte[] buffer = new byte[AllocSize * 1024];

            sum += buffer[0];

            if (GC.CollectionCount(0) != gcCount)
            {
                return i;
            }
        }

        return MaxBudget + sum;
    }

在不同的机器上尝试,将返回不同的值。例如,在功能强大的台式机,笔记本电脑和Windows手机上试用它。