c# 如何在 .NET 应用中启用 Server GC 模式

Server GC 是针对服务器工作负载优化的垃圾回收模式,需通过 runtimeconfig.json 设置 "System.GC.Server": true 或环境变量 DOTNET_gcServer=1 启用;启用后 GCSettings.IsServerGC 必须返回 true 才生效。

Server GC 是什么,为什么需要手动启用

在 .NET 5+ 中,Server GC 默认已启用(针对服务器工作负载优化:多代并行回收、独立线程、更大堆),但 .NET Core 3.0–3.1 或某些容器/服务托管环境(如 Windows Service、IIS 非默认配置)可能仍运行在 Workstation GC 模式下。这会导致 GC 暂停时间偏长、吞吐量下降,尤其在高并发 Web API 或后台处理服务中明显。

判断当前模式最直接的方式是检查 System.Runtime.GCSettings.IsServerGC —— 它返

true 才算真正启用了 Server GC。

通过 runtimeconfig.json 启用(推荐,构建时确定)

这是最稳定、无侵入、适用于所有托管场景的方式。修改项目生成的 MyApp.runtimeconfig.json(通常在 bin/Debug/net6.0/ 下),确保包含 gcServer 配置项:

{
  "runtimeOptions": {
    "tfm": "net6.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "6.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

⚠️ 注意:System.GC.Server 是配置键名,不是类名或命名空间;值必须为 JSON 布尔字面量 true(不能是字符串 "true");该文件由 SDK 在发布(dotnet publish)时生成,因此应在项目文件中声明:

  • .csproj 中添加:
    
      true
    
  • 重新 dotnet publish,SDK 会自动注入 System.GC.Server: trueruntimeconfig.json

通过环境变量临时覆盖(调试/容器部署常用)

当无法修改构建配置(如已有 Docker 镜像、第三方部署平台),可用环境变量强制切换:

  • Windows:set DOTNET_gcServer=1
  • Linux/macOS:export DOTNET_gcServer=1
  • Docker:docker run -e DOTNET_gcServer=1 myapp

⚠️ 该变量只在进程启动前读取,运行时修改无效;且优先级低于 runtimeconfig.json,若两者冲突,以配置文件为准。

代码中调用 GCSettings.TryStartNoGCRegion 不代表启用了 Server GC

常见误解:以为调用 GCSettings.LatencyMode = GCLatencyMode.LowLatencyGC.TryStartNoGCRegion 就等于启用了 Server GC。其实这些只是 GC 行为微调,与 GC 模式无关。

验证是否生效的唯一可靠方式是启动后立即检查:

Console.WriteLine($"IsServerGC: {GCSettings.IsServerGC}"); // 必须输出 True

如果输出 false,说明配置未生效——优先排查 runtimeconfig.json 是否被覆盖、环境变量拼写是否为 DOTNET_gcServer(大小写敏感)、是否在 Main 入口前就已初始化 GC(比如某些 DI 容器提前触发了 GC)。

Server GC 的堆结构和线程模型与 Workstation GC 完全不同,一旦启用错误,可能引发 OutOfMemoryException(因初始堆更大)或 GC 线程争用(在极低负载下反而更慢)。别只看开关开了,要实测 IsServerGC 和 GC 暂停指标。