【问题标题】:What are the Generations in Garbage Collection?垃圾收集的世代是什么?
【发布时间】:2011-01-16 11:39:39
【问题描述】:

我不明白垃圾收集上下文中的“世代”是什么。谁能简单的解释一下?

【问题讨论】:

    标签: .net garbage-collection


    【解决方案1】:

    来自Understanding Garbage Collection in .NET

    世代

    分代垃圾收集器 多收集短命的对象 经常比寿命更长的。 短期对象存储在 第一代,0代。 寿命更长的物体被推入 更高的世代,1 或 2。 垃圾收集器工作更多 经常在低代 比更高的。

    当一个对象第一次被创建时,它是 放入第 0 代。当 第0代被填满,垃圾 收集器被调用。那些对象 在垃圾收集中幸存下来 第一代被提升到 下一代更高一代,第 1 代。 在垃圾中幸存的对象 第 1 代的收集是 晋升到下一个和最高的 一代,2代。这 算法有效地适用于 对象的垃圾收集,因为它 很快。请注意,第 2 代是 最高的一代 由垃圾收集器支持。

    Garbage Collection in .NET

    世代

    内存分配时 托管堆很快,GC本身 可能需要一些时间。考虑到这一点 进行了多项优化 以提高性能。 GC 支持世代的概念, 基于这样的假设 一个对象在堆上的时间更长, 它可能会停留的时间越长 那里。当一个对象被分配到 它属于第 0 代的堆。 每个垃圾收集器 对象生存增加其 1代(目前最高 支持的世代是 2)。明显地 搜索速度更快,并且 垃圾收集所有的子集 堆上的对象,所以 GC 有 仅收集一代的选项 0、1 或 2 个对象(或其他 它选择的组合,直到它有 足够的内存)。即使在 GC 只收集较年轻的对象 还可以确定旧对象是否有 对新对象的引用以确保 它不会无意中忽略 正在使用的对象。

    【讨论】:

    • “显然搜索更快,并且垃圾收集堆上所有对象的子集......” - 我认为这句话具有误导性。 AFAIU,GC 不能只搜索一代——它必须从根开始,不管它们是哪一代,并且每次都构建完整的图。它也不能跳过将幸存对象推广到下一代。 AFAIU,它唯一可以真正跳过的就是压缩老一代?主要优点是所有非垃圾都被提升和复制到 gen 之外。 0个空间,结果就可以一口气刷完?
    【解决方案2】:

    “Pro C# 2008”中有一个很好的描述:

    1. 第 0 代标识了一个从未标记为收集的新创建对象
    2. 第 1 代标识了一个在 GC 中幸存下来的对象(标记为收集但未删除,因为有足够的堆空间)
    3. 第 2 代识别出一个在不止一次 GC 扫描中幸存下来的对象。

    【讨论】:

    • 你写道:“第 1 代标识了一个在 GC 中幸存下来的对象(标记为收集但没有被删除,因为有足够的堆空间)” - 你不是说:第 1 代标识了一个对象在 GC 中幸存下来(在运行垃圾收集时没有被删除,因为它仍然有对它的引用)?
    • @BornToCode 不,MS 实现似乎使用了一种预算机制,其中给 Gen1 推荐的内存量。它仅在超过此数量时起作用。这减少了 GC 实际操作的次数,从而提高了性能。但是,该空间不等于最大可用堆空间。介于两者之间。
    【解决方案3】:

    我的博客, Generations of Garbage Collection,回答你的问题:

    CLR 的垃圾收集器 (GC) 是一种分代垃圾收集器,也称为临时垃圾收集器。

    它分为三代:

    0代:

    它包含所有新构建的对象,这些对象从未被 GC 检查过。

    第一代:

    CLR 在初始化时为第 0 代选择一个以 kb 为单位的预算大小。如果对象的创建导致第 0 代超出其预算,则开始垃圾收集。第 0 代中未收集的对象被移到第 1 代,第 0 代被清空。 假设第 0 代的预算等于 5 个对象的大小。因此,在创建对象 6 之前,第 0 代将如下所示:

    在创建对象 6 后,垃圾分配开始,这将释放垃圾对象 1、3 和 5,并在第 1 代中将 2 和 4 移动到彼此相邻的位置。

    第 1 代的预算大小也是由 CLR 在初始化时选择的。对象 11 的创建会导致 GC 重新开始,这可能会将更多对象移动到第 1 代。

    第 1 代被忽略用于垃圾收集,直到它达到垃圾收集的预算大小,这提高了 GC 的性能。

    第二代:

    在多次第 0 代收集中,第 1 代可能会超出其预算限制,从而导致 GC 从两代收集垃圾。在这种情况下,第 1 代幸存者被提升到第 2 代,第 0 代幸存者被提升到第 1 代,第 0 代为空。

    假设分配对象 21 导致垃圾收集和第 1 代预算已达到。

    所以堆看起来像下面这样,在第 1 代中幸存的对象被提升到第 2 代。

    所以基本上 Generation GC 假定较新的对象更有可能被收集。

    我们知道 CLR 会为所有三代选择预算,但它可以修改它们,因为 GC 是一个自我调整的收集器。如果 GC 在收集到第 0 代后发现存活的对象很少,它可能会决定减少第 0 代的预算,从而完成更少的工作。另一方面,如果 GC 收集第 0 代并看到有很多幸存对象,则在垃圾收集中没有回收很多内存。在这种情况下,垃圾收集器将增加第 0 代的预算。 GC 也会相应地修改第 1 代和第 2 代的预算。

    【讨论】:

    • 这是这里最清晰、最深入的答案 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多