.NET Core 垃圾收集(GC)

在本章中,我们将介绍垃圾收集的概念,这是 .NET 托管代码平台最重要的功能之一。垃圾收集器(GC)管理内存的分配和释放。垃圾收集器充当自动内存管理器。

  • 您不需要知道如何分配和释放内存或管理使用该内存的对象的生命周期。
  • 每当您使用 new 关键字声明对象或值类型被装箱时,都会进行分配。分配通常非常快。
  • 当没有足够的内存来分配对象时,GC 必须收集并处理垃圾内存,以使内存可用于新的分配。
  • 这个过程称为垃圾收集(Garbage Collection,即 GC)。

垃圾收集的优点

垃圾收集有以下优点:

  • 在开发应用程序时,不需要手动释放内存。
  • 它还有效地在托管堆上分配对象。当对象不再使用时,它将通过清除内存来回收这些对象,并将内存保留为将来的分配。
  • 托管对象自动获得干净的内容,所以它们的构造函数不必初始化每个数据字段。
  • 它还通过确保对象不能使用其他对象的内容来提供内存安全性。

垃圾收集的条件

垃圾收集在下列条件就会时发生:

  • 当系统的物理内存较低时。
  • 托管堆上分配的对象使用的内存超过了可接受的阈值。该阈值在流程运行时不断调整。
  • GC.Collect 方法被调用。当然在一般条件下,都不必调用此方法,因为垃圾收集会自动且始终运行。这种方法主要用于独特的情况和测试。

阶段过程

.NET 垃圾收集器有 3 代,每一代都有自己的堆,用于存储分配的对象。有一个基本的原则,判定大多数对象是短暂的还是长期的。

第一代 (0)
  • 在第 0 代中,首先分配对象。
  • 在这一代,对象通常不会超越第一代,因为在下一次垃圾收集时,它们不再被使用(超出范围)。
  • 0 代很快收集,因为它相关的堆很小。
第二代 (1)
  • 在第 1 代,对象有第二个机会空间。
  • 在第 0 代收集(通常是基于巧合的时机)下寿命很短的对象会转到第 1 代。
  • 1 代集合也很快,因为它的关联堆也很小。
  • 前两堆仍然很小,因为对象被收集或提升到下一代堆。
第三代 (2)
  • 在第二代,所有的长对象都是活动的,它的堆可以很大。
  • 这一代的对象可以长期存活下去,没有下一代堆积对象可以进一步推广。垃圾收集有一个额外的堆,用于称为大对象堆(LOH)的大型对象。它保留 85,000 字节或更大的对象。
  • 大对象并没有分配到代堆,而是直接分配给了 LOH。
  • 第二代和 LOH 收集可能会花费很长时间运行的程序或运行大量数据的程序。
  • 已知大型服务器程序在十几个 GB 中堆积如山。
  • GC 采用各种技术来减少阻止程序执行的时间。
  • 主要方法是在后台线程上尽可能多地执行垃圾回收工作,而不会干扰程序执行。
  • GC 还为开发人员提供了一些方法来影响其行为,这对提高性能非常有用。