管中窥豹----.NETCore到.NET8托管堆的变迁

程序员有二十年 2024-11-02 10:58:40
简介

https://www.cnblogs.com/lmy5215006/p/18494483在研究.NET String底层结构时,我所观察到的情况与《.NET Core底层入门》,《.NET内存管理宝典》书中描述不符。故多研究了一下。发现.NET托管堆的结构也是越来越多,越来越高性能。

//示例代码internal Program {public const string constStr = "Lewis.liu";static void Main(string[] args) {string name = "Lewis";var person = Person.name;var str = constStr; Debugger.Break(); Console.ReadKey(); } }public Person {public static string name = "liu"; }.NET Core 3的托管堆结构

标准的SOH(0代,1代,2代),LOH结构,因此String Intern作为JIT编译阶段就能确定的静态内容,如果放在SOH堆中,就不太合适。存放在LOH堆中反而是更好的选择,因为LOH中没有升代,没有压缩,内存地址也不会移动。更加适合静态数据。

眼见为实----堆结构

眼见为实----是否分配在LOH

三个静态数据的内存地址

它们的GC 引用根三个静态数据都引用了同一个gcroot

GC根分配在LOH

.NET 5的托管堆结构

大家可以思考一个问题,LOH堆的定义是指>=85000byte的大对象才会进入的堆。而静态数据只是利用了LOH的特性,但本质与LOH描述不符,属于投机取巧的行为。也会给开发者带来困扰,比如说我。因此在.NET 5 以后,CLR开发人员新增了一个Pinned object heap ,用于存储固定对象的特殊堆。来解决定义不匹配的问题

眼见为实----POH

眼见为实----是否分配在POH

.NET 8的托管堆结构

到了.NET 8 中,CLR团队又新增了NonGC heap ,顾名思义,这代表一个不会被GC的托管堆。很奇怪吧?那有人就有疑问了? POH堆不是已经完美了吗?为什么还要新增堆?CLR团队给出了答案主要是为了提高性能,没有写屏障,没有GC。这大大提高了效率

https://github.com/dotnet/runtime/blob/main/docs/design/features/NonGC-Heap.md

眼见为实----NonGC heap

眼见为实----是否分配在NonGC Heap

结论

CLR对静态数据存放一直都在优化,从最早的LOH到POH再到NonGC,在研究sting.Intern的过程中走了不少弯路。因此大家在参考市面上的书籍时,切记知行合一,眼见为实。否则用过时的知识去分享就贻笑大方啦

0 阅读:0

程序员有二十年

简介:感谢大家的关注