点击上方蓝字 江湖评谈设为星标
前言
GC的性能优化,在.NET Core1.0就有了。比如把GC调成服务器运作模式,另外一个就是工作站模式。这两种模式有什么区别呢?工作站模式直接点就是C/S模式,也就是为客户端应用程序设计的。它的特点是占用资源少,内存少,基于这两点也导致了吞吐量,扩展性,程序性能的相应的受到一定的影响。服务器模式是为大规模的服务设计的,比如高性能,高并发,集群,微服务等等。服务器模式更倾向于大量资源,大块内存,更高的性能,更高的吞吐量。服务器模式每个CPU逻辑核心都有一个专用堆,每个堆有一个单独线程控制。
可以看到服务器模式的优缺点,如果能把服务器模式的缺点比如资源占用和复杂性进一步降低,做到接近或者平衡到工作站模式的需求的资源水平,而不降低服务器模式的吞吐量性能。这是一个非常好的优化点,本篇来看下。
概述
为解决以上所提出的优化点,.NET8里面GC服务器模式支持动态堆计数。添加了一个【动态适应应用程序大小】也叫做DATAS的功能,因为这个功能是新添加的,所以即使在.NET8它也是默认关闭的。但是注意了Native AOT发布的时候,它默认是开启的。如果要想开启它,非常简单,在Csproj项目文件里面设置如下项即可:
<GarbageCollectionAdaptationMode>true</GarbageCollectionAdaptationMode>
或者通过环境变量:DOTNET_GCDynamicAdaptationMode =1
CMD:
set DOTNET_GCDynamicAdaptationMode =1
PowerShell:
$env:DOTNET_GCDynamicAdaptationMode =1
Uninx/Linux:
export DOTNET_GCDynamicAdaptationMode =1
DATAS能够随着时间的增加来增加或者减少堆计数,试图(注意这里是试图,而不是必须)对其吞吐量最大化,并在此和总体内存占用之间保持平衡。
下看一个例子:
//dotnet run -c Release -f net8.0
using System.Diagnostics;
for (int i = 0; i < 32; i++)
{
new Thread(() =>
{
while (true) Array.ForEach(new byte[1], b => { });
}).Start();
}
using Process process = Process.GetCurrentProcess();
while (true)
{
process.Refresh();
Console.WriteLine($"{process.WorkingSet64:N0}");
Thread.Sleep(1000);
}
当运行这个程序的时候,结果如下:
154,226,688
154,226,688
154,275,840
154,275,840
154,816,512
154,816,512
154,816,512
154,824,704
154,824,704
154,824,704
在以上示例的csproj里面添加DATAS
<GarbageCollectionAdaptationMode>true</GarbageCollectionAdaptationMode>
它的运行结果如下
71,430,144
72,187,904
72,196,096
72,196,096
72,245,248
72,245,248
72,245,248
72,245,248
72,245,248
72,253,440
工作集的性能显著提高,工作集显著下降
往期精彩回顾