0

我有这个简单的代码:

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。

…</p>

可能有多个垃圾收集,但只有在第 1 代达到其预算时才检查第 1 代中的对象,这通常需要第 0 代的几次垃圾收集。

问题 :

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

我不明白的行是第 7 行。

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

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

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

我错过了什么?

ps这里是包含书中确切文本的链接(相信我我有PDF)

4

4 回答 4

3

在给本书作者写了一封电子邮件后,

这是他的回答

预算用于告诉 GC IT 应该收集哪些代。如果您自己调用 GC.Collect,那么您是在告诉 GC 忽略预算并只进行收集。您正在强制收集早期的对象,从而将对象推广给老一代。

于 2012-04-08T17:36:11.340 回答
1

我相信达米安是正确的。这本书描述了当你不强制进行完全垃圾收集时会发生什么。但你这样做。因此,正确的文本可能是这样的:

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

于 2012-04-08T11:24:01.427 回答
1

不要相信你在书中读到的一切。

作者写这本书时,他/她可能还没有完全理解这个主题。在作者写完这本书之后,实现可能已经发生了变化。

以下是我的理解:

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

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

于 2014-09-14T15:10:27.267 回答
1

这是一种测试 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 手机上试用。

于 2014-09-15T20:15:14.623 回答