@
palfortime 知乎作者原文里有介绍
自古以来的服务器应用都是一台服务器跑一个 server app ,然后让 server app 最大化内存占用,用空间换时间,一台机器撑起大量的流量。所以你会看到 Java 、老版本的 .NET 在 server 上动辄几个 G 的内存占用。
毕竟向操作系统频繁申请和归还内存是一件很消耗性能的事情,因此很多语言都更倾向于一次性 commit 大量内存,然后留着自己管理,即使有可用空间也不会立即进行 decommit 。这样一来当有瞬时的大量内存需求时可以快速地将内存提供给负载用,提升整体性能。
然而云原生时代一切都变了,每一个 server app 都跑在了容器上,由 k8s 等来调度,一台服务器上可能会跑很多的 server app 容器,这就使得以前那种用大量空间换时间的做法失效了:因为占用的资源越少意味着能够调度的容器越多,同时也意味着更容易进行横向扩展,灵活性变的更高。而以前的用空间换时间的做法在云原生时代反而是个累赘。
.NET 自然也是要适应时代变化,因此大概两三年前就开始新的 GC 的设计和实现工作。到了 .NET 9 这项工作终于迎来正式发布,引入了新的 DATAS GC 代替原有的 Server GC 。
这个新的 GC 可以根据实际的应用程序负载来动态调节所需的内存,在不需要的时候快速将多余的内存归还给操作系统,从而大幅度削减内存占用。
然而 GC 并不能坐时光机预测未来的负载如何变化,因此 DATAS GC 下了大量的功夫去设计各种 heuristics ,从而能正确的预测和调节各托管堆大小,让申请下来的内存和实际需要的内存尽可能一致,据说这些 heuristics 甚至用了机器学习来优化过。
在实际测试结果中,DATAS GC 相比原来的 Server GC 节省了 70%~90% 的内存,原来要 1G 内存的 server app 现在只需要不到 200mb 。官方给出的 ASP .NET Core 的 TechEmpower JSON benchmark 测试中,内存占用相比原来更是直接暴降了 93%,直接从原来的 1.6G 降到了现在的 120mb ,要知道 TechEmpower 可是大量并发的压力测试: