日韩欧美国产精品免费一二-日韩欧美国产精品亚洲二区-日韩欧美国产精品专区-日韩欧美国产另-日韩欧美国产免费看-日韩欧美国产免费看清风阁

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

.NET Core 堆結(jié)構(gòu)(Heap)底層原理淺談

freeflydom
2024年12月14日 10:51 本文熱度 985

.Net托管堆布局

加載堆

主要是供CLR內(nèi)部使用,作為承載程序的元數(shù)據(jù)。

  1. HighFrequencyHeap
    存放CLR高頻使用的內(nèi)部數(shù)據(jù),比如MethodTable,MethodDesc.

通過is判斷類型之間的繼承關(guān)系,調(diào)用接口的方法和虛方法,都需要訪問MethodTable

  1. LowFrequencyHeap
    存放CLR低頻使用的內(nèi)部數(shù)據(jù),比如EEClass,ClassLoader.

GC信息與異常處理表,它們都只在發(fā)生時才訪問,因此訪問頻率不高。

  1. StringLiteralMap
    字符串駐留池:https://www.cnblogs.com/lmy5215006/p/18494483

字符串對象本身存儲在FOH堆中,String Literal Map只是一個索引

  1. StubHeap
    函數(shù)入口的代碼堆
  2. CodeHeap
    JIT編譯代碼使用的內(nèi)部堆,比如生成IL。
  3. VirtualCallStubHeap
    虛方法調(diào)用的內(nèi)部堆

使用!eeheap -loader可以查看

眼見為實

新版sos呈現(xiàn)方式不一樣,可以使用老版sos展示文中所述內(nèi)容

托管堆

大家的老朋友了,不做過多解釋,由GC統(tǒng)一管理的內(nèi)存堆.一個.NET程序中所有的Domain都會共用一個托管堆

  1. SOH
    略略略
  2. LOH
    略略略
  3. POH
    固定對象專屬的堆,比如非托管線程訪問托管對象,就需要把對象固定起來,避免被GC回收造成非托管代碼的訪問違例.

使用!eeheap -gc可以查看

眼見為實

凍結(jié)堆

.NET8推出來的一個新堆,用來存放永遠(yuǎn)不會被GC管理的永生對象,比如string 字面量。
簡單來說,就是一個對象你都永遠(yuǎn)不會釋放了,還放在托管堆就是浪費了。不如單獨拎出來存。

眼見為實

https://www.cnblogs.com/lmy5215006/p/18515971

上述所說的各種堆,只是一個邏輯上的概念。作為內(nèi)存的物理承載。由堆段(Heap Seg-ment)實現(xiàn).
簡單來說,段是托管堆的物理表示。

眼見為實

segmentbeginallocatedcommitted allocated sizecommitted size
段指針的對象地址內(nèi)存分配的起始點內(nèi)存分配的末尾點已提交的分配大小已提交的大小

SOH小對象堆

堆只是一個抽象的概念,在物理上的表現(xiàn)形式為內(nèi)存段,作為CLR細(xì)化堆的一種管理單位。多個段組成了堆。

.NET8之前的段結(jié)構(gòu)

在.NET 8 之前,段分為SOH,LOH,POH 三個段。
對于SOH段有點特殊,因為段上面還有分代邏輯。包含0代和1代的對象只會分配在新分配的內(nèi)存段上(臨時段),剩下的每個段都是2代的段

可以看到,代只是一個邏輯概念,并沒有獨立的段空間。0,1,2代共享段空間。

.NET8的段結(jié)構(gòu)

到了.NET 8,代已經(jīng)不是一個邏輯概念,而是一個物理概念。
每個代都有了自己獨立的段空間。

代機(jī)制

每當(dāng)GC觸發(fā)時,所有對象(非固定)都會進(jìn)行升代,直到gen2為止。

  1. obj對象剛創(chuàng)建,為0代
    內(nèi)存地址為0x00000263ee009528,0x01fb08000028>0x000001fb080b71e0>01fb080b9068 說明obj放在0代里
  2. 第一次GC,obj升為1代
    內(nèi)存地址在1代空間范圍內(nèi)
  3. 第二次GC,obj升為2代
    內(nèi)存地址在2代空間范圍內(nèi)

代邊界

細(xì)心的朋友會發(fā)現(xiàn)一個盲點,就是obj剛剛創(chuàng)建的時候,0代內(nèi)存起始點為0263ee000028,升為1代后,1代內(nèi)存起始點也變?yōu)榱?263ee000028,2代也同樣。
這就引申出另一個概念,GC升代,不是簡單的copy對象從0代到1代。而是移動代的邊界。
每次GC觸發(fā)時,代邊界指針會在多個“地址段”上遷移,通過這種邏輯操作,達(dá)到性能的最高,可以觀察上面的 Allocated 區(qū),一會給了 0gen,一會又給了 1gen,一會又給了 2gen

LOH大對象堆

大對象堆存儲所有>=85000byte的對象,但也是有例外。LOH堆上對象管理相對寬松,沒有“代”機(jī)制,默認(rèn)情況下也不會壓縮。

例外1-32位環(huán)境下的double[]

        static void Main(string[] args)
        {
            double[] array1 = new double[999];
            Console.WriteLine(GC.GetGeneration(array1));
            double[] array2 = new double[1000];
            Console.WriteLine(GC.GetGeneration(array2));
            double[,] array3 = new double[32,32];
            Console.WriteLine(GC.GetGeneration(array3));
            long[] array4 = new long[1000];
            Console.WriteLine(GC.GetGeneration(array4));
            Debugger.Break();
            Console.ReadKey();
        }

這里有個很奇怪的現(xiàn)象,在32位環(huán)境下,array2的大小= 4b+4+4+1000*8=8012byte. 遠(yuǎn)遠(yuǎn)<=85000byte. 為什么被分配到了LOH堆?
這主要跟內(nèi)存對齊有關(guān),double的未對齊訪問非常昂貴,遠(yuǎn)遠(yuǎn)超過long,ulong,int。這對于64位環(huán)境來說不是問題,總是對SOH與LOH使用8byte對齊。但對于4字節(jié)對齊的32位環(huán)境。這就是個大問題了.
所以CLR開發(fā)團(tuán)隊決定將閾值大于1000的double放入LOH堆(LOH堆總是8byte對齊)。避免了double未對齊訪問的巨大成本

例外2-StringInter與靜態(tài)成員以及元數(shù)據(jù)

https://www.cnblogs.com/lmy5215006/p/18515971
參考此文,在.NET5之前沒有POH堆,所以CLR內(nèi)部使用的三個數(shù)組也會進(jìn)入LOH堆。
三個數(shù)組分別為

  1. static對象的object[]
  2. 字符串池 object[]
  3. 元數(shù)據(jù) RuntimeType object[]

其實很好理解,這些都是低頻變化的內(nèi)容,放在LOH堆上好過放在SOH堆。

POH堆

POH堆解決了什么問題?
從.NET5開始,CLR團(tuán)隊給pinned的對象單獨放入一個段中,這樣pinned對象不會和普通對象混在一起。導(dǎo)致大量細(xì)小Free空間。從而降低托管堆碎片化,也降低了代降級的頻次。

有點遺憾的是,非托管代碼造成的對象固定,并不會移動到POH堆中。因此代降級的現(xiàn)象依舊存在。
感覺未來微軟可以重點優(yōu)化這塊,固定對象是GC速度最大的阻礙。

如何使用POH堆?

在.NET 8中,將對象放入POH堆是一種“有意為之”行為,必須調(diào)用 GC 類提供的 AllocateArray 和 AllocateUninitializedArray 方法并設(shè)置 pinned=true

FOH

FOH堆解決了什么問題?
在.NET8中,如果一個對象在創(chuàng)建的時候,就明確知道是“永生”對象,那就沒必要納入托管堆的管理范圍,只會徒增GC的工作量。因此干脆把對象放在托管堆之外,來提高性能

常見的例子就是字符串的字面量(literal)

static對象布局,不會被GC回收的對象1

靜態(tài)的基元類型(short,int,long) ,它的值本身并不存放在托管堆上。而是存放在Domain中的高頻堆中

靜態(tài)的引用類型則不同。真正的對象存放在托管堆上,再由POH中一個object[]持有,最后被高頻堆中的m_pGCStatics所管理

Domain下每一個Module都維護(hù)了一個DomainLocalModule結(jié)構(gòu),靜態(tài)變量放在該Module中

眼見為實:靜態(tài)基元類型分配在高頻堆上?

    internal class Program
    {
        static long age = 10086;
        static void Main(string[] args)
        {
            age = 12;
            Console.WriteLine("done. " + age);
            Debugger.Break();
        }
    }


通過匯編得知,static a的地址為00007ff9a618e4a8

觀察高頻堆地址可以發(fā)現(xiàn),00007FF9A6180000<00007ff9a618e4a8<00007FF9A6190000 。明顯屬于高頻堆

眼見為實:靜態(tài)引用類型分配在哪?

    internal class Program
    {
        public static Person person = new Person();
        static void Main(string[] args)
        {
            var num = person.age;
            Console.WriteLine(num);
            Debugger.Break();
        }
    }
    public class Person
    {
        public int age = 12;
    }
  1. 使用!gcwhere命令來查看person對象屬于0代中,說明對象本身分配在托管堆

  2. 使用!gcroot命令查看它的引用根,發(fā)現(xiàn)它被一個object[]所持有

  3. 再查看object[]的所屬代,可以看到該對象屬于POH堆

  4. bp coreclr!JIT_GetSharedNonGCStaticBase_Helper 下斷點來獲取 DomainLocalModule 實例

    注意,這里我重新運行了一遍,所以object[]內(nèi)存地址有變

字符串駐留池布局,不會被GC回收的對象2

關(guān)于字符串的不可變性,參考此文:https://www.cnblogs.com/lmy5215006/p/18494483

在.NET8之前,字符串駐留與靜態(tài)引用類型處理模式無差別。
.NET 8加入FOH堆之后,會將編譯期間就能確定的字符串放入FOH堆,以便提高GC性能。

眼見為實

        static void Main(string[] args)
        {
            var str1 = "hello FOH";//編譯期間能確定
            var str2 = Console.ReadLine();
            string.Intern(str2);//運行期間才能確定
            Console.WriteLine($"str1={str1},str2={str2}");
            Debugger.Break();
        }
  1. 編譯期間能確定的,直接加入了FOH

  2. 運行期間確定,與靜態(tài)引用類型處理流程一致

轉(zhuǎn)自https://www.cnblogs.com/lmy5215006/p/18583743


該文章在 2024/12/14 10:51:40 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 日韩欧美在线网址 | 国产精品极品美女自在线观看免费 | 国产在线视频国产 | 欧美理论片在线观看一区二区 | 日韩精品中文字幕一区二区三区 | 国产欧美日韩一区二区三区在 | 亚洲宅男精品一区在线观看 | 国产福利高颜 | 免费国产小视频 | 真人一级一级99片黄大片 | 欧美精品一区二区三区四 | 野花社区视频在线观看 | 色777狠狠狠 | 欧美日韩国产一线天午夜秀场 | 亚洲a在线观看 | 欧美黑人又粗又大又爽免费 | 亚洲精品综合色区二区 | 亚洲免费综合色在线视频 | 偷窥国产 | 私人电影官网 | 国产h视频在线观看网 | 三级高清精品国产 | 亚洲人成电影手机在线播放 | 午夜电影这里只有精品 | 口国产自 | 亚洲中文娱乐网在线观看 | 欧美性大| 国产精品边做奶水狂喷有码 | 日本高清不卡aⅴ免费网站 精品国产污 | 国产精品日产三 | 亚洲日韩一区二区 | 亚洲欧美综合在线天堂 | 国产日韩欧美一区二区三区精品 | 91中文字日产乱幕 | 大地资源第二页中文高清版 | 国产日韩欧美一区二区三区精品 | 国产福利在线观看极品美女 | 日韩中文免费视频 | 免费人成网视频 | 日韩中文高清一 | 色哒哒影院 |