CLR的核心功能之一就是垃圾回收(garbage collection),关于GC的基本概念本文不在赘述。这里主要针对GC的两种工作模式展开讨论和研究。

Workstaction模式介绍

该模式设计的目的是用于客户端类的应用(Client),这类应用的部署特点是同一台机器会部署很多应用程序,并且这些应用程序的性能要求并没有服务器程序(nginx、asp.net等)那么高。那么在此种场景下,GC做了哪些设计和调整呢?

  1. 首先,最显著的特点是当触发垃圾回收时,CLR并没有安排专用的线程来执行垃圾回收操作,仅仅是使用当前触发GC的线程去执行后续操作,并且连线程优先级都没有提升。那么自然GC操作就要和其它用户线程来平等竞争CPU使用。
  2. 其次,GC堆的数量上也仅仅只有1组(1个大对象堆、1个小对象堆),这样可以更少的占用内存空间。

Server模式介绍

顾名思义,Server模式就是针对服务器场景设计的,此类应用的部署特点是服务器内存大CPU核心多,部署的程序数量少(基本都是专机专用),但是对程序性能要求非常高。于是这种模式下,GC的也做了相应的调整:

  1. 基于CPU核心多的特点,CLR则分配专用的线程(按照CPU核心数分配)来执行GC操作,且专用线程的优先级为THREAD_PRIORITY_HIGHEST,也比普通托管线程更高。这样当需要执行GC时可以保证优先占用CPU,从而尽快完成GC操作,尽快满足内存申请所需空间。
  2. 基于内存大的特点,那就多分配GC堆,且每个堆更大,从而避免频繁的触发GC。具体来说,GC堆数量是根据CPU核心数来分配,比如8核CPU就分配8组GC堆。至于堆的默认大小,将按照如下规则分配:

注意上表的值是每个堆的大小,对多核CPU来说,Server模式的GC堆分配空间显然是大于Wordstation模式的。

什么是后台垃圾回收(Background)?

我们知道CLR根据GC次数把对象分为0代、1代、2代。其中01代执行的频率高、耗时短,也被称为ephemeral generations。 根据CLR的设计,执行01代垃圾回收时,所有托管线程是被短暂挂起,直到垃圾回收结束后再恢复执行。但是执行2代的垃圾回收会耗时相对更长,如果也挂起全部线程,无疑会对程序响应造成较大的影响。

因此CLR提出单独分配专用线程,用来执行2代垃圾回收,且此线程执行时不会挂起其它线程,从而降低对程序的影响。注意此处2代垃圾回收其实是包含了之前的01代的,只不过01代执行很短暂且01代执行时会依旧会挂起全部线程。

关于Background专用线程的数量,workstation模式拥有1个专用线程,server模式分配和逻辑处理器数量一致的专用线程。

在workstation模式下background回收的执行示意图:

上图的解读:

  1. GC THREAD就是background专用线程,可以看到其执行期间,其它线程没有影响。
  2. 其中绿色箭头代表01代的回收操作,可以看到其执行就是在普通的THREAD1线程,而且挂起了其它所有线程。

在server模式下background回收的执行示意图:

上图解读:

  1. GC THREAD1/2代表01代的专用线程,BGC THREAD1/2代表background专用线程。
  2. 同样的background线程执行回收时,其它线程不受影响。
  3. 绿色箭头代表01代的回收操作,可以看到挂起了其它所有线程。

需要额外说明是,background是最新的叫法,之前版本称为concurrent。他们之间的升级关系如下:

  workstation模式 server模式
.NET Framework 4之前 concurrent gc 不支持
.NET Framework 4 background gc 不支持
.NET Framework 4.5及之后 background gc background gc

二个模式的对比

  workstation模式 server模式 说明
专用线程 有单独的专用线程,且数量等于CPU核心数 server模式充分利用多核特性,最大化保证快速完成GC操作。
gc执行的优先级 普通 THREAD_PRIORITY_HIGHEST workstation模式线程执行GC操作需要和普通业务线程平等竞争CPU,GC不能最快的完成。
gc堆数量 1 多个,数量等于CPU核心数

workstation模式堆数量少且内存更少,但是容易引起GC。

server模式堆数量多占用内存更多,可以降低触发GC的次数,进而提高程序的响应性能。

background支持情况 支持,但只会分配1个background专用线程 支持,分配的background专用线程数量等于CPU核心数

怎么设置不同工作模式?

项目文件csproj中设置:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>
</Project>

runtimeconfig.json 文件设置:

{
"runtimeOptions":{
"configProperties":{
"System.GC.Server":true,
"System.GC.Concurrent":true
}
}
}

单独说明一点,对于单核CPU的计算机,无论如何配置都是workstation模式,当然现代计算机这种情况极少了。

通过dump验证上述机制

对于workstation模式的程序进程,通过dump查看gc堆信息和gc模式信息分别如下:

0:004> !eeversion
6.0.21.52210 free
Workstation mode
SOS Version: 6.0.5.7301 retail build 0:004> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000024E80001030
generation 1 starts at 0x0000024E80001018
generation 2 starts at 0x0000024E80001000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
0000024E80000000 0000024E80001000 0000024E8010DFE8 0000024E80112000 0x10cfe8(1101800) 0x111000(1118208)
Large object heap starts at 0x0000024E90001000
segment begin allocated committed allocated size committed size
0000024E90000000 0000024E90001000 0000024E9004FD40 0000024E90050000 0x4ed40(322880) 0x4f000(323584)
Pinned object heap starts at 0x0000024E98001000
0000024E98000000 0000024E98001000 0000024E98006C50 0000024E98012000 0x5c50(23632) 0x11000(69632)
Total Allocated Size: Size: 0x161978 (1448312) bytes.
Total Committed Size: Size: 0x160000 (1441792) bytes.
------------------------------
GC Allocated Heap Size: Size: 0x161978 (1448312) bytes.
GC Committed Heap Size: Size: 0x160000 (1441792) bytes.

对于server模式的程序进程,通过dump查看gc堆信息和gc模式信息分别如下:

查看代码
0:012> !eeversion
6.0.21.52210 free
Server mode with 8 gc heaps
SOS Version: 6.0.5.7301 retail build 0:015> !eeheap -gc
Number of GC Heaps: 8
------------------------------
Heap 0 (000001E88D3F3AD0)
generation 0 starts at 0x000001E88EF51030
generation 1 starts at 0x000001E88EF51018
generation 2 starts at 0x000001E88EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001E88EF50000 000001E88EF51000 000001E88EF51048 000001E88EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001EC8EF51000
segment begin allocated committed allocated size committed size
000001EC8EF50000 000001EC8EF51000 000001EC8EF51018 000001EC8EF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED0EF51000
000001ED0EF50000 000001ED0EF51000 000001ED0EF53010 000001ED0EF62000 0x2010(8208) 0x11000(69632)
Allocated Heap Size: Size: 0x2070 (8304) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 1 (000001E88D41F830)
generation 0 starts at 0x000001E90EF51030
generation 1 starts at 0x000001E90EF51018
generation 2 starts at 0x000001E90EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001E90EF50000 000001E90EF51000 000001E90EF51048 000001E90EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001EC9EF51000
segment begin allocated committed allocated size committed size
000001EC9EF50000 000001EC9EF51000 000001EC9EF51018 000001EC9EF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED1EF51000
000001ED1EF50000 000001ED1EF51000 000001ED1EF51018 000001ED1EF52000 0x18(24) 0x1000(4096)
Allocated Heap Size: Size: 0x78 (120) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 2 (000001E88D426EE0)
generation 0 starts at 0x000001E98EF51030
generation 1 starts at 0x000001E98EF51018
generation 2 starts at 0x000001E98EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001E98EF50000 000001E98EF51000 000001E98EF51048 000001E98EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001ECAEF51000
segment begin allocated committed allocated size committed size
000001ECAEF50000 000001ECAEF51000 000001ECAEF51018 000001ECAEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED2EF51000
000001ED2EF50000 000001ED2EF51000 000001ED2EF51430 000001ED2EF52000 0x430(1072) 0x1000(4096)
Allocated Heap Size: Size: 0x490 (1168) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 3 (000001ED9B54AFB0)
generation 0 starts at 0x000001EA0EF51030
generation 1 starts at 0x000001EA0EF51018
generation 2 starts at 0x000001EA0EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001EA0EF50000 000001EA0EF51000 000001EA0EF51048 000001EA0EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001ECBEF51000
segment begin allocated committed allocated size committed size
000001ECBEF50000 000001ECBEF51000 000001ECBEF51018 000001ECBEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED3EF51000
000001ED3EF50000 000001ED3EF51000 000001ED3EF51018 000001ED3EF52000 0x18(24) 0x1000(4096)
Allocated Heap Size: Size: 0x78 (120) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 4 (000001ED9B576570)
generation 0 starts at 0x000001EA8EF51030
generation 1 starts at 0x000001EA8EF51018
generation 2 starts at 0x000001EA8EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001EA8EF50000 000001EA8EF51000 000001EA8EF51048 000001EA8EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001ECCEF51000
segment begin allocated committed allocated size committed size
000001ECCEF50000 000001ECCEF51000 000001ECCEF51018 000001ECCEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED4EF51000
000001ED4EF50000 000001ED4EF51000 000001ED4EF51018 000001ED4EF52000 0x18(24) 0x1000(4096)
Allocated Heap Size: Size: 0x78 (120) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 5 (000001ED9B5A2420)
generation 0 starts at 0x000001EB0EF51030
generation 1 starts at 0x000001EB0EF51018
generation 2 starts at 0x000001EB0EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001EB0EF50000 000001EB0EF51000 000001EB0EF673D8 000001EB0EF72000 0x163d8(91096) 0x21000(135168)
Large object heap starts at 0x000001ECDEF51000
segment begin allocated committed allocated size committed size
000001ECDEF50000 000001ECDEF51000 000001ECDEF51018 000001ECDEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED5EF51000
000001ED5EF50000 000001ED5EF51000 000001ED5EF53010 000001ED5EF62000 0x2010(8208) 0x11000(69632)
Allocated Heap Size: Size: 0x18400 (99328) bytes.
Committed Heap Size: Size: 0x22000 (139264) bytes.
------------------------------
Heap 6 (000001ED9B5CE2D0)
generation 0 starts at 0x000001EB8EF51030
generation 1 starts at 0x000001EB8EF51018
generation 2 starts at 0x000001EB8EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001EB8EF50000 000001EB8EF51000 000001EB8EF51048 000001EB8EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001ECEEF51000
segment begin allocated committed allocated size committed size
000001ECEEF50000 000001ECEEF51000 000001ECEEF51018 000001ECEEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED6EF51000
000001ED6EF50000 000001ED6EF51000 000001ED6EF51018 000001ED6EF52000 0x18(24) 0x1000(4096)
Allocated Heap Size: Size: 0x78 (120) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
Heap 7 (000001ED9B5FA180)
generation 0 starts at 0x000001EC0EF51030
generation 1 starts at 0x000001EC0EF51018
generation 2 starts at 0x000001EC0EF51000
ephemeral segment allocation context: none
segment begin allocated committed allocated size committed size
000001EC0EF50000 000001EC0EF51000 000001EC0EF51048 000001EC0EF52000 0x48(72) 0x1000(4096)
Large object heap starts at 0x000001ECFEF51000
segment begin allocated committed allocated size committed size
000001ECFEF50000 000001ECFEF51000 000001ECFEF51018 000001ECFEF52000 0x18(24) 0x1000(4096)
Pinned object heap starts at 0x000001ED7EF51000
000001ED7EF50000 000001ED7EF51000 000001ED7EF51018 000001ED7EF52000 0x18(24) 0x1000(4096)
Allocated Heap Size: Size: 0x78 (120) bytes.
Committed Heap Size: Size: 0x2000 (8192) bytes.
------------------------------
GC Allocated Heap Size: Size: 0x1ab58 (109400) bytes.
GC Committed Heap Size: Size: 0x30000 (196608) bytes.

总结

本文主要参阅了微软官方文档,对GC的工作模式进行了探究和验证。可以看到,微软设计这2个GC工作模式的目的是为了.net应用程序在不同场景下有好的程序表现,并没有孰优孰劣的问题。这个功能特点可以类比现在自动挡汽车的工作模式有节能模式、道路模式、雪地模式、沙漠模式一样。因此,在实际开发程序时,对普通客户端应用如winfrom一般选择workstation模式,对于服务器程序如asp.net 一般选择server模式。

参考资料

  1. 垃圾回收的基本知识 | Microsoft Docs
  2. Workstation vs. server garbage collection (GC) | Microsoft Docs
  3. 后台垃圾回收 | Microsoft Docs
  4. 垃圾回收器配置设置 - .NET | Microsoft Docs

CLR的GC工作模式介绍(Workstation和Server)的更多相关文章

  1. 讨论.NET Core 配置对GC 工作模式与内存的影响

    引出问题: Asp.net core应用在 Kubernetes上内存使用率过高问题分析 https://mp.weixin.qq.com/s/PqhUzvFpzopU7rVRgdy7eg 这篇文章中 ...

  2. .NET Core 配置GC工作模式与内存的影响

    .NET Core 配置GC工作模式与内存的影响 .NET Core GC 原文:https://blog.markvincze.com/troubleshooting-high-memory-usa ...

  3. rsync的介绍及参数详解,配置步骤,工作模式介绍

    rsync的介绍及参数详解,配置步骤,工作模式介绍 rsync是类unix系统下的数据镜像备份工具.它是快速增量备份.全量备份工具. Sync可以远程同步,支持本地复制,或者与其他SSH.rsync主 ...

  4. 【RabbitMQ】工作模式介绍

    一.前言 之前,笔者写过< CentOS 7.2 安装 RabbitMQ> 这篇文章,今天整理一下 RabbitMQ 相关的笔记便于以后复习. 二.模式介绍 在 RabbitMQ 官网上提 ...

  5. LVS的工作模式介绍和NAT模式&DR模式实验步骤

    一:LVS介绍 二.LVS的NAT和DR模式的实验及配置步骤 一.LVS的简单介绍 linux virtual server 简单来讲lvs是一段内核代码 类似于netfilter本身是一框架但不提供 ...

  6. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_10.RabbitMQ研究-工作模式-路由工作模式介绍

    队列在绑定交换机的时候可以指定routingKey, 路由模式: 1.每个消费者监听自己的队列,并且设置routingkey. 2.生产者将消息发给交换机,由交换机根据routingkey来转发消息到 ...

  7. .NET 中 GC 的模式与风格

    垃圾回收(GC)是托管语言必备的技术之一.GC 的性能是影响托管语言性能的关键.我们的 .NET 既能写桌面程序 (WINFROM , WPF) 又能写 web 程序 (ASP.NET CORE),甚 ...

  8. LVS工作模式与调度算法

    LVS三种工作模式.十种调度算法介绍 工作模式介绍: 1.Virtual server via NAT(VS-NAT) 优点:集群中的物理服务器可以使用任何支持TCP/IP操作系统,物理服务器可以分配 ...

  9. 【嵌入式开发】ARM 芯片简介 (ARM芯片类型 | ARM处理器工作模式 | ARM 寄存器 | ARM 寻址)

    : 12MHz 晶振 对应 405 ~ 532 MHz 处理速度; -- : 16K 指令缓存, 16K 数据缓存; -- : 32KB 指令缓存, 32KB 数据缓存; (3) 内存接口对比 : 提 ...

随机推荐

  1. for、while、do...while循环结构

    循环结构分别有: while 循环 do...while 循环 for 循环 在Java5中引入了一种主要用于数组的增强型for循环 while 循环 while是最基本的循环,它的结构为: whil ...

  2. NOIP2018 Day2T3 保卫王国

    首先不考虑强制要求的话是一个经典问题,令 \(f_{i, 0 / 1}\) 为 \(i\) 选或不选时以 \(i\) 为根的子树的最优答案.那么就有转移 \(f_{u, 0} = \sum f_{v, ...

  3. VC 获取已系统安装的字体

    转载请注明来源:https://www.cnblogs.com/hookjc/ BOOL CALLBACK EnumFonts(CONST LOGFONT* lplf, CONST TEXTMETRI ...

  4. V8 内存管理和垃圾回收机制总结

    这篇文章主要介绍 V8 的内存管理和垃圾回收知识. V8 内存管理及垃圾回收机制浅析 由于 V8 引擎的原因,Node 在操作大内存对象时受到了一些限制,在 64 位的机器上,默认最大操作的对象大小约 ...

  5. python基础1-类属性和实例属性

    类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似.对于公有的类属性,在类外可以通过类对象和实例对象访问 类属性 class ...

  6. Java和Js编码(encodeUrl)解码(decodeUrl)对空格的差异问题

    今天解决一个问题的时候遇到了一个编码解码问题,记录一下. 1. Js用的是encodeURIComponent()方法编码,后面的都以该编码方式处理出来的数据为准. 2. Java用的是URLDeco ...

  7. Worms

    474B Worms time limit per test 1 second memory limit per test 256 megabytes input standard input out ...

  8. 07.python语法入门--流程控制

    分支结构 什么是分支结构 为什么要用分支结构 如何使用分支结构 if语法 if应用案例 循环结构 什么是循环结构 为什么要用循环结构 如何使用循环结构 while循环语法 while循环应用案例 fo ...

  9. Solution -「LOCAL」客星璀璨之夜

    \(\mathcal{Description}\)   OurOJ.   给定坐标轴上的 \(2n+1\) 个坐标 \(x_1,x_2,\cdots,x_{2n+1}\),其中偶数下标的位置是一个小球 ...

  10. verification 时间不推进,挂起

    时间不推进,挂起 0时刻 windows-> new -> source Browser 可能是仿真精度不够,比如进度是1ns,但是时钟有0.1ns为周期的,这种情况下,仿真器会吧这个周期 ...