c# 服务器GC和工作站GC的区别和设置
技术百科
煙雲
发布时间:2026-01-02
浏览: 次 服务器GC是Web服务默认选择,.NET运行时自动启用;工作站GC仅适用于单用户桌面应用。可通过GCSettings.IsServerGC或性能计数器验证,配置优先级为环境变量>csproj>自动检测。
工作站GC适合单用户桌面应用,服务器GC才是Web服务的默认选择
ASP.NET Core 或传统 ASP.NET 应用在 IIS 或 Kestrel 上运行时,默认启用的是 server GC,不是 workstation GC。这个决定由运行时自动判断——只要检测到多核 CPU 和非交互式环境(比如 Windows Server 或 Linux 容器),.NET 运行时就会启用服务器 GC。你手动改错配置,反而可能让 GC 压力更大、暂停更长。
如何确认当前用的是哪种 GC 模式
最直接的方式是查 System.Runtime.GCSettings.IsServerGC 的返回值:
Console.WriteLine($"IsServerGC: {System.Runtime.GCSettings.IsServerGC}");也可以通过性能计数器验证(Windows):.NET CLR Memory\# of Heaps 在服务器 GC 下通常是 CPU 核心数的 2 倍(每个线程池线程对应一个 GC 线程 + 后台 GC 线程),而工作站 GC 固定为 1 个堆。
常见误判点:
- 本地开发时跑在 Windows 10 上,但用了
,结果没生效——因为 .NET 6+ 默认按运行环境自动选型,显式配置只在项目文件中有效且需重启进程true - 容器里跑 Linux,却依赖 Windows 性能计数器去查,查不到就以为没启服务器 GC
在 csproj 中强制设置 GC 模式(仅限需要干预时)
绝大多数 Web 服务不需要改,但如果你在低配 VM(如 1 vCPU)上跑高吞吐 API,或做 GC 行为对比测试,才考虑显式控制。修改方式是在 .csproj 文件的 里加:
true
注意:
-
true= 服务器 GC(推荐 Web 服务);false= 工作站 GC(适合 WinForms/WPF) - 该设置只在编译时写入 runtimeconfig.json,运行时无法动态切换
- 若同时设置了环境变量
DOTNET_gcServer,它会覆盖 csproj 配置(优先级:环境变量 > csproj > 自动检测) - 在 Docker 中,建议用
ENV DOTNET_gcServer=true而不是改 csproj,避免镜像复用时配置僵化
服务器GC的关键行为差异和实际影响
服务器 GC 不是“更快的 GC”,而是“为吞吐和并发设计的 GC”:
- 堆数量 = CPU 核心数 × 2(.NET 5+ 默认启用
concurrent GC,后台线程独立工作) - 每次 GC 暂停时间更长(毫秒级),但频率更低,整体吞吐更高
- 内存占用通常比工作站 GC 高 10%–30%,因为各堆独立管理,碎片和保留内存更多
- 不支持
GC.Collect()的“紧急回收”语义——调用它只会触发本线程所在堆的 GC,其他堆不受影响 - 在 .NET 6+ 中,
GCSettings.LatencyMode(如GCLatencyMode.LowLatency)对服务器 GC 效果有限,仅短暂抑制后台 GC,不能替代正确对象生命周期管理
真正容易被忽略的是:服务器 GC 下的 Gen2 回收成本极高,如果频繁分配大对象(>85KB),会直接进 LOH,而 LOH 在服务器 GC 中不压缩(除非 .NET 5+ 开启 gcServer + gcConcurrent 并配合 GCSettings.LargeObjectHeapCompactionMode 显式触发),长期运行后容易出现 OutOfMemoryEx
ception —— 这不是 GC 类型选错了,是对象尺寸或复用策略有问题。
# windows
# win
# linux
# js
# json
# docker
# 环境变量
# 并发
# 对象
# 堆
# 区别
# 内存占用
# c#
# .net
# 线程
# iis
# wpf
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在Golang中使用闭包_封装变量与函数作用域
- Mac怎么给文件夹加密_Mac创建加密磁盘映像教程
- 如何在Golang中配置代码格式化工具_使用gof
- Win10系统更新错误0x80240034怎么办
- 如何使用正则表达式批量替换重复的“-”模式为固定字
- C#如何序列化对象为XML XmlSerializ
- Windows10任务栏图标变成白色文件_Win1
- c++协程和线程的区别 c++异步编程模型对比【核
- 微信JSAPI支付回调PHP怎么接收_处理JSAP
- Python函数参数高级用法_默认值与可变参数解析
- Python性能剖析高级教程_cProfileLi
- php嵌入式需要什么环境_搭建php+linux嵌
- 如何在Golang中操作嵌套切片指针_Golang
- 如何在Golang中处理二进制数据_Golang
- 如何在Golang中解压文件_Golang com
- C#如何使用Channel C#通道实现异步通信
- Python项目维护经验_长期演进说明【指导】
- LINUX怎么查看进程_LINUX ps命令查看运
- 短链接怎么用php还原_从基础原理到代码实现教学【
- Win11怎么开启智能存储_Windows11存储
- Mac如何修改Hosts文件?(本地开发与屏蔽网站
- 本地php环境打开php文件直接下载_浏览器解析p
- Win11开机Logo怎么换_Win11自定义启动
- php与c语言在嵌入式中有何区别_对比两者在硬件控
- Win11关机快捷键是什么_Win11快速关机方法
- 如何使用Golang encoding/json解
- PHP接收参数值为空怎么办_判断和处理空参数方法说
- Win11此电脑不在桌面上_Windows 11桌
- MAC如何修改默认应用程序_MAC文件后缀关联设置
- Win10如何更改开机密码_Windows10登录
- Linux怎么禁止Root用户远程登录_Linux
- Win11怎么关闭触摸屏_禁用Win11笔记本触摸
- mac怎么退出id_MAC退出iCloud账号与A
- php8.4xdebug无法调试怎么办_php8.
- php怎么下载安装后设置错误日志_phpini l
- Win10如何更改用户账户控制_Windows10
- Win11怎么关闭触控板_Win11笔记本禁用触摸
- Python函数接口稳定性_版本演进解析【指导】
- Golang如何避免指针逃逸_Golang逃逸分析
- mac怎么安装adb_MAC配置Android A
- Win11快速助手怎么用_Win11远程协助连接教
- Win11怎么关闭专注助手 Win11关闭免打扰模
- C++如何使用std::async进行异步编程?(
- Python随机数生成_random模块说明【指导
- Win11怎么更改账户头像_Windows 11自
- php中::能访问全局变量吗_全局作用域与类作用域
- MAC如何启用访达侧边栏显示_MAC Finder
- Win11怎么设置虚拟内存_Windows 11优
- Win11怎么关闭任务栏小组件_Windows11
- Win11怎样安装钉钉客户端_Win11安装钉钉教

QQ客服