在垃圾收集器GEN 2中进行清洁的情况

时间:2013-11-29 11:34:36

标签: asp.net garbage-collection

在ASP.Net中,有人可以告诉我内存是从垃圾收集器GEN 2中释放出来的吗?

2 个答案:

答案 0 :(得分:1)

当满足下列条件之一时,就会发生垃圾收集:

  1. 系统物理内存较低。

  2. 托管堆上已分配对象使用的内存超过了可接受的阈值。在该过程运行时,该阈值会不断调整。

  3. 调用GC.Collect方法。几乎在所有情况下,您都不必调用此方法,因为垃圾收集器会持续运行。此方法主要用于特殊情况和测试。

  4. 第2代。这一代包含长寿命对象。长期对象的一个​​示例是服务器应用程序中的一个对象,该对象包含在该过程期间处于活动状态的静态数据。

    在条件允许的情况下,垃圾收集会在特定世代中发生。收集一代意味着收集那一代及其所有年轻一代的物品。第2代垃圾回收也称为完整垃圾回收,因为它回收了所有代中的所有对象(即托管堆中的所有对象)。

    标记阶段,用于查找并创建所有活动对象的列表。 重定位阶段,用于更新对将要压缩的对象的引用。

    压缩阶段,用于回收死亡物体占据的空间并压缩幸存的物体。压缩阶段将垃圾收集中幸存的对象移动到段的旧端。

    由于第2代集合可以占用多个细分,因此可以将升级为第2代的对象移动到较旧的细分中。第1代和第2代幸存者都可以移动到不同的部分,因为它们被提升为第2代。

    通常,大对象堆不会被压缩,因为复制大对象会降低性能。但是,从.NET Framework 4.5.1开始,您可以使用GCSettings.LargeObjectHeapCompactionMode属性按需压缩大对象堆。

    垃圾收集器使用以下信息来确定对象是否处于活动状态:

    1. 堆栈根。堆栈变量由实时(JIT)编译器和堆栈walker提供。

    2. 垃圾收集句柄。指向托管对象的句柄,可以由用户代码或公共语言运行库分配。

    3. 静态数据。应用程序域中的静态对象,可以引用其他对象。每个应用程序域都会跟踪其静态对象。

    4. 在垃圾收集开始之前,除了触发垃圾收集的线程之外,所有托管线程都将被挂起。 下图显示了一个触发垃圾收集并导致其他线程被挂起的线程。触发垃圾收集的线程。

答案 1 :(得分:1)

我认为你的问题的简单答案是当收集是大对象堆(LOH)时垃圾发生的第2代。当LOH被填满时,它将触发一个完整的集合,并且调用垃圾收集器的Gen2。

因此,如果您的应用程序分配并释放大量大型对象(大多数超过100k),那么这也可能是一个触发点。

您可以参考此MSDN了解详情。

来自Large Object Heap Uncovered

  

从代的角度来看,大型对象属于第2代   因为只有在第2代时才收集它们   收集。当收集一代人时,所有年轻一代   也被收集。所以例如,当一代1垃圾   收集发生,收集第1代和第0代。当一个   发生第2代垃圾收集,收集整个堆。   因此,第2代垃圾收集也称为a   完整的垃圾收集。在本专栏中,我将使用术语“生成”   2垃圾收集而不是完整的垃圾收集,但它们是   可互换的。

enter image description here

  

该图说明了在第2代垃圾收集之后   你看到Obj1和Obj2死了,我形成了一个自由空间   以前被Obj1和Obj2占用的内存   然后用于满足Obj4的分配请求。空间   在最后一个对象Obj3之后,直到段的结尾仍然可以   用于满足进一步的分配请求。