浅入.NerCore GC

前言

.NET 中GC管理你服务的内存分配和释放,GC是运行公共语言运行时(CLR Common Language Runtime)中,GC可以帮助开发人员有效的分配内存和和释放内存,大多数情况下是不需要去担心的,但是有时候服务总是是出现莫名的问题,所以还是有必要了解一下GC的基础知识的。这里就不介绍内存方面的知识了。

GC回收过程

GC 将对象分为大对象和小对象,如果对象的大小大于或者等于 85000byte 将被视为大对象,大对象会被分配到到 (LOH) Large Object Heap 中去。

GC 有一个代数的概念 Generation,分为三代

  • Generation 0: 0代,这里面都是生命周期很短的对象,比如临时变量,当你new一个对象的时候该对象都会在Generation 0中,这里的对象将很快的被GC回收,但是当你new的是一个大对象的时候它会直接进去大对象堆(LOH)

  • Generation 1: 1代,这一代包含的也基本是生命周期很短的对象。它是短期对象和长期对象之间的缓冲区。

  • Generation 2: 2代,这一代包含的都是生命周期长的对象,它们都是从1代和2代中选拔出来的,LOH属于2代。

当分配的对象使用的内存超出了 GC 的阈值时回收就会开始。阈值是随着服务的运行 GC 自己调整的。或者直接调用 GC.Collect 方法也可以开始回收。

回收开始时 GC 会开始循环遍历 Generation 0 中的所有对象并标记所有对象是活动对象还是非活动对象,标记完成后会更新活动对象的引用。最后会回收非活动对象占用的内存,并把活动对象压缩后移动到 Generation 1 中,Generation 1 中的或对象在移动到 Generation 2 是默认不会被压缩的,因为复制大的对象会导致性能的下降。可以通过 GCSettings.LargeObjectHeapCompactionMode 来配置压缩 LOH

GC的回收类型

GC 回收有两种类型,WorkStation GC(工作站) 和 Server GC(服务器),.Net Core服务默认情况下时使用WorkStation GC工作站模式来回收。

  • Server GC 会拥有更大的内存,Server GC 会为每个处理器创建一个用于执行垃圾回收的堆和专用线程,每个堆都拥有一个小对象堆和大对象堆,并且所有的堆都可以访问。 不同堆上的对象可以相互引用。因为多个垃圾回收线程一起工作,所以对于相同大小的堆Server GC 垃圾回收比 WorkStation GC 垃圾回收更快一些。但是 Server GC 回收会占用大量资源,这种模式的特点是初始分配的内存较大,并且尽可能不回收内存,进行回收用时会很耗时,并进行内存碎片整理工作。

  • Workstation GC 的内存相对于 Server GC 就很小啦,且它的回收线程就是服务的线程且有较高的优先级,因为必须与其他线程竞争 CPU 时间来进行回收。

不同模式下的内存分配

GC的回收模式

GC 有三种回收模式

  • Non-Concurrent GC 非并行回收模式:在非并行模式下,回收时候会挂起所有其他的线程影响服务的性能。

  • Concurrent GC 并行回收模式: 并行会后可以解决非并行回收引起的线程挂起,让其他线程和回收线程一起运行,使服务可以更快的响应,并行回收只会发生在 Generation 2 中,Generation 0/1 始终都是非并发的,因为他们都是小对象回收的速度很快。在并行回收的时候我们依旧可以分配对象到 Generation 0/1 中。

  • Background GC 后台回收模式:Background GCConcurrent GC的增强版本。 区别在Background GC回收Generation 2的时允许了Generation 0/1 进行清理。在WorkStation GC下会使用一个专用的后台垃圾回收线程,而Server GC下会使用多个线程来进行回收。且Server GC下回收线程不会超时。

非并行回收:

并行回收

WorkStation GC 后台回收

Server GC 后台回收

GC回收类型配置

推荐使用 runtimeconfig.template.json 文件和环境变量 COMPlus_gcServer 来配置。

COMPlus_gcServer 0 = WorkStation GC
COMPlus_gcServer 1 = Server GC

1
2
3
4
5
6
7
{
"configProperties": {
"System.GC.Server": true
//true - Server GC false - WorkStation GC
}

}

GC回收模式配置

推荐使用runtimeconfig.json文件和环境变量COMPlus_gcConcurrent来配置。

COMPlus_gcConcurrent 0 =Non-Concurrent GC
COMPlus_gcConcurrent 1 =Background GC

1
2
3
4
5
6
7
8
{

"configProperties": {
"System.GC.Concurrent": true
//true- Background GC false -Non-Concurrent GC
}

}

强制回收

在一些特殊的情况下强制回收是可以提高服务的性能的,可以向 GC.Collect() 提供 GCCollectionMode 枚举值触发强制回收。

  • Default :默认的回收设置。
  • Forced :立即强制进行垃圾回收。
  • Optimized : GC 来判断时间是否是回收对象的最佳时间,如 GC 判定回收效率不高因此回收不合理的情况下将返回不回收对象。
1
GC.Collect( (int) GCCollectionMode.Forced);

延迟回收

在我们的服务在检索数据或者处理逻辑的时候可能会发生垃圾回收,从而妨碍性能,可以通过 System.Runtime.GCLatencyMode 来配置延迟回收

  • GCLatencyMode.LowLatency:禁止 Generation 2 回收,只回收 Generation 0/1 ,这个只能在短时间内使用,如果长时间使用内存处于压力下 GC 还是会触发回收,这个配置只对 WorkStation GC 可用。

  • GCLatencyMode.SustainedLowLatency :禁止 Generation 2Foreground GC(前台回收),只回收 Generation 0/1Generation 2 后台回收。WorkStation GCServer GC 都可以使用,且可以长时间使用,但是如果禁用Background GC,将无法使用。

1
GC.Collect( (int) GCLatencyMode.SustainedLowLatency);

参考文章

从ASP.NET Core 3.0 preview 特性,了解CLR的Garbage Collection

微软文档

总结

简单了解了一下GC如何工作,文中有错误请在评论区留言。


浅入.NerCore GC
http://example.com/posts/52738.html
作者
她微笑的脸y
发布于
2022年6月15日
许可协议