.Net CLR GC plan_phase二叉樹和Brick_table

楔子

Plan_Phase(GC的計劃階段)很早就接觸了,但是后面一直沒用到,忘記了,此次又用到了,幾乎忘光了,費了很大力氣理解它,記錄下,以免又忘記了。

主題

計劃階段(plan_phase)主要就兩個部分,一個是堆里面的對象構建一顆龐大的二叉樹。但是,這個二叉樹如果過于龐大,則成了性能瓶頸。于是乎,第二個部分Brick_table出現了,它主要是分割這個龐大的二叉樹,以消弭性能瓶頸問題。

構建不規則二叉樹

構建二叉樹之前,先了解一些概念。當實例化一個對象之后,這個對象存儲在堆里面。堆實際上是一長串的內存地址,不受CPU棧的管控,所以導致了它不能自動釋放,需要手動。在這一長串的地址里面,可以分為固定對象和非固定對象。

1.固定對象概念

首先看下固定句柄,固定句柄就是把托管對象傳遞到費托管對象的堆棧里面去,固定句柄本身在托管里面進行管理,而它包含的對象就叫做固定對象。

至于非固定對象,就是普通的對象了,此處不再贅述。

在進行GC計劃階段的時候,會循環遍歷當前需要收集的垃圾的代(generation)里面包含的所有堆,然后區分出包含固定對象的堆段,和非固定對象的堆段。

區分規則是怎么樣的呢?非常簡單,具體的就是如果相鄰的兩個對象都是非固定對象或者都是固定對象,則把這兩個對象作為一個堆段,繼續查找后面的對象。如果后續的對象跟前面的對象相同,則跟前面的兩個對象放在一起形成一個堆段(如果后面還有相同的,則繼續放在一起),如果不同,則此堆段到此為止。后面繼續以同樣的邏輯遍歷,形成一個個的小堆段(以node表述)。

2.這里有一個特性:

固定堆段(也就是固定對象組成的堆段)的末尾必須跟一個非固定對象(這么做的原因,是避免固定對象的末尾被覆蓋,只覆蓋非固定對象的末尾)。

二叉樹的構建,就建立在這些固定對象堆段和非固定對象堆段上的。這些一個個的堆段作為二叉樹的根節點和葉子結點,構成了二叉樹的本身。

3.相關構建

一:plug_and_pair結構
plug_and_pair存在于上面被分割的堆段的前面,堆段以node(節點)表示,則此結構(plug_and_pair*)node)[-1]的位置

struct plug
{uint8_t *  skew[plug_skew / sizeof(uint8_t *)];
};class pair
{public:short left;short right;
};
struct plug_and_pair
{pair        m_pair;plug        m_plug;
};

pair的left和right成員分別表示當前堆段距離其前一個堆段和后一個堆段的距離長度。

二:構建邏輯
構建邏輯分為三種,數字一般可以分為奇數和偶數。計算機也是一樣,但是除了這兩種之外,偶數里面還可以分裂出另外一種情況,就是一個數字是2的次方數。舉個例子,比如:1,2,3,4,5,6,7,8,9,10。這十個數字里面,明顯的奇數:1,3,5,7,9。偶數:2,4,6,8,10。再分裂下二的次方數:2,4,8。注意看,最后分裂的結果2,4,8分別是2的1次方,2次方和3次方。剔除了6和10這兩個數字。
那么總結下,三種邏輯以上面試個數字舉例分別為:
遍歷循環以上十個數字。
第一種(if(true)):1,2,4,8 if(!(n&(n-1))) n分別為2,4,8。if里為true
第二種(if(true)):3,5,7,9 if(n&1) n分別為1,3,5,7,9。if里為true
第三種(if(true)):6,10 如果以上兩種不成立,則到第三種這里來。

三:構建樹身
如上所述,通過對堆里面的對象進行固定和非固定對象區分,變成一個個的小堆段(node)。這些小堆段從左至右依次編號:1,2,3,4,5,6,7,8,9.......N。然后通過構建邏輯這部分進入到if里面去。

1.(if(true)):

1,2,4,8編號的node會進入這里,主要是設置左節點和tree
set_node_left_child (new_node, (tree - new_node));tree = new_node;

2.(if(true)):

3,5,7,9編號的node會進入這里,主要是設置右節點
set_node_right_child (last_node, (new_node - last_node));

3.(if(true)):

6,10編號的會進入這里,主要是把原來的二叉樹的右子節點變成新的node(new_node)的左子節點,切斷二叉樹與它自己右子節點的聯系。然后把新的node(new_node),變成原來二叉樹的右子節點。uint8_t*  earlier_node = tree;size_t imax = logcount(sequence_number) - 2;//這里是獲取需要變成的二叉樹的右子樹節點的層級。for (size_t i = 0; i != imax; i++)//如果層級不等于0,則獲取到二叉樹根節點到右子節點的距離,然后把根節點與右子節點相加得到二叉樹右子節點。如此循環遍歷,到二叉樹最底層的右子節點為止。{earlier_node = earlier_node + node_right_child (earlier_node);}獲取到最后一顆二叉樹的根節點的右子樹的距離int tmp_offset = node_right_child (earlier_node);assert (tmp_offset); // should never be empty把最后一顆二叉樹的根節點和最后一顆二叉樹的右子節點相加,設置為新的node(new_node)的左子樹。set_node_left_child (new_node, ((earlier_node + tmp_offset ) - new_node));把最后一顆二叉樹的右子樹節點設置為新的node(new_node)節點,同時也是斷了開與原來右子樹的聯系。set_node_right_child (earlier_node, (new_node - earlier_node));

GC plan_phase的二叉樹構建本身并不復雜,而是復雜的邏輯和詭異的思維方式。

最終的構建的二叉樹形式如下圖所示:
0f584535c85e81ed0f8a17109cf00aac.png

四.分割二叉樹
當以上二叉樹被構建之后,如有幾千個節點(node,小堆段)會形成龐大的一棵樹。所以需要分割功能,用以來保證性能。

當二叉樹包含的小堆段(node)的長度超過2的12次方(4kb),這棵二叉樹就會被分割。

4bdafb816378b9c58c4f097af2e6eca0.png

Brick_table里面屬于這個4節點范圍內的都是賦值為-1,表示你要在4節點上尋找你需要的節點。

源碼:

最后上一下源碼
1.構建二叉樹:

uint8_t* gc_heap::insert_node (uint8_t* new_node, size_t sequence_number,uint8_t* tree, uint8_t* last_node)
{dprintf (3, ("IN: %Ix(%Ix), T: %Ix(%Ix), L: %Ix(%Ix) [%Ix]",(size_t)new_node, brick_of(new_node),(size_t)tree, brick_of(tree),(size_t)last_node, brick_of(last_node),sequence_number));if (power_of_two_p (sequence_number)){set_node_left_child (new_node, (tree - new_node));dprintf (3, ("NT: %Ix, LC->%Ix", (size_t)new_node, (tree - new_node)));tree = new_node;}else{if (oddp (sequence_number)){set_node_right_child (last_node, (new_node - last_node));dprintf (3, ("%Ix RC->%Ix", last_node, (new_node - last_node)));}else{uint8_t*  earlier_node = tree;size_t imax = logcount(sequence_number) - 2;for (size_t i = 0; i != imax; i++){earlier_node = earlier_node + node_right_child (earlier_node);}int tmp_offset = node_right_child (earlier_node);assert (tmp_offset); // should never be emptyset_node_left_child (new_node, ((earlier_node + tmp_offset ) - new_node));set_node_right_child (earlier_node, (new_node - earlier_node));dprintf (3, ("%Ix LC->%Ix, %Ix RC->%Ix",new_node, ((earlier_node + tmp_offset ) - new_node),earlier_node, (new_node - earlier_node)));}}return tree;
}

2.切割二叉樹:

size_t gc_heap::update_brick_table (uint8_t* tree, size_t current_brick,uint8_t* x, uint8_t* plug_end)
{dprintf (3, ("tree: %Ix, current b: %Ix, x: %Ix, plug_end: %Ix",tree, current_brick, x, plug_end));if (tree != NULL){dprintf (3, ("b- %Ix->%Ix pointing to tree %Ix",current_brick, (size_t)(tree - brick_address (current_brick)), tree));set_brick (current_brick, (tree - brick_address (current_brick)));//brick_table索引處的值是:根節點tree距離當前current_brick對應的地址的距離}else{dprintf (3, ("b- %Ix->-1", current_brick));set_brick (current_brick, -1);}size_t  b = 1 + current_brick;ptrdiff_t  offset = 0;size_t last_br = brick_of (plug_end-1);//上一個plug節點的末尾current_brick = brick_of (x-1);//當前的plug_startdprintf (3, ("ubt: %Ix->%Ix]->%Ix]", b, last_br, current_brick));while (b <= current_brick){if (b <= last_br){set_brick (b, --offset);}else{set_brick (b,-1);}b++;}return brick_of (x);
}

以上參考:
https://github.com/dotnet/coreclr/blob/main/src/gc/gc.cpp

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281174.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281174.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281174.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vijos p1484 ISBN號碼

描述每一本正式出版的圖書都有一個ISBN號碼與之對應&#xff0c;ISBN碼包括9位數字、1位識別碼和3位分隔符&#xff0c;其規定格式如“x-xxx-xxxxx-x”&#xff0c;其中符號“-”就是分隔符&#xff08;鍵盤上的減號&#xff09;&#xff0c;最后一位是識別碼&#xff0c;例如0…

scrapy爬蟲啟示錄-小伙子老夫看你血氣方剛這本《爬蟲秘錄》就傳給你了

文章來源&#xff1a; IT源點 第一章 誤入歧途 每個學習爬蟲的人都有一顆愛美的心&#xff0c;俺也是一樣的。那么多的美眉圖片&#xff0c;不薅下來&#xff0c;沒了誰負責。于是夜里孤枕難眠的老男孩開始了他的擼碼之旅。從此在學習爬蟲&#xff0c;學習Python的道路上越走…

自己設置假期的日歷控件_在假期旅行時使用PC娛樂自己

自己設置假期的日歷控件Staying connected may be hard no matter what network you are on, and in flight Wi-Fi isn’t pervasive enough to count on. Here are tips and tricks to keep yourself entertained when unplugged and traveling. 無論您使用什么網絡&#xff0…

.Net CLR異常和windows C++ 異常調用棧簡析

楔子前面一篇研究了下C異常的&#xff0c;這篇來看下&#xff0c;CLR的異常內存模型&#xff0c;實際上都是一個模型&#xff0c;承繼自windows異常處理機制。不同的是&#xff0c;有VC編譯器(vcruntime.dll&#xff09;接管的部分&#xff0c;被CLR里面的函數ProcessCLRExcept…

Codeforces936C. Lock Puzzle

給個串&#xff0c;只能用操作shift x表示把后面x個字符翻轉后放到串的前面。問s串怎么操作能變t串。n<2000&#xff0c;操作次數<6100。 打VP時這轉來轉去的有點暈。。。 可以想一種逐步構造的方法&#xff0c;即從一個小的完成構造的部分通過一頓操作&#xff0c;在不影…

公共服務領域英文譯寫規范_公共領域日:對版權和公共領域重要性的思考

公共服務領域英文譯寫規范The first of the year is Public Domain Day, a day intended to call attention to copyright issues and the public domain. At the Center for the Study of the Public Domain they have an interesting (and sobering) review of works that wo…

Elasticsearch 實戰經驗總結

Centos7下es 7.7.0安裝配置 怎么安裝使用elasticsearch-head插件 用logstash同步Mysql數據到ES Springboot使用ES官方推薦方式REST Client整合ES實現關鍵詞高亮 ELK-Elasticsearch&#xff0c;Logstash&#xff0c;kibana搭建基于日志文件的日志分析系統 設置elasticsearc…

.Net 7 的 AOT 和 CLR有什么區別?

楔子&#xff1a;AOT和 CLR的區別是什么呢&#xff1f;大部分人肯定會說&#xff0c;一個編譯成本地機器碼&#xff08;Native Code&#xff09;&#xff0c;一個是JIT即時編譯的結果。這么說&#xff0c;其實也對&#xff0c;但是不具體。具體應該怎么看呢&#xff1f;AOTAOT實…

接入amazon avs_每日新聞綜述:亞馬遜將互聯網接入推向全球的宏偉計劃

接入amazon avsPlus Snap’s big push to stay relevant, Amazon’s Alexa-powered AirPods alternatives, more Android Q news, and a lot more. It’s time to talk about the biggest, coolest, or generally most interesting stories from the last 24 hours. 加上Snap保…

計算的未來

我自己倒是后來也是覺得我自己可以想象一個未來的技術&#xff0c;就是以后的編程的語言和庫可以抽象現在的一些高級語言的關鍵字。比如要寫一個編輯器的時候&#xff0c;只要給點這些東西的數據結構和數據流向&#xff0c;而一些什么很繁瑣的一些底層編碼都是可以用高級語言來…

nginx 實用配置問題總結

配置 tomcat&#xff0c;nginx&#xff0c;解決 post 請求超時問題nginx 跨域問題 CORS policy: No Access-Control-Allow-Originnginx 配置靜態驗證文件&#xff0c;報 404&#xff0c;解決方案nginx 獲取用戶真實 IPcentos 部署 php 網站方法-使用 nginx ssl https

零部件分類屬性

離散制造業的研發、生產跟產品零部件緊密聯系在一起&#xff0c;從企業業務流程來說零部件涉及研發、采購、倉儲、生產、質量、售后和配件等多個部門&#xff0c;為了更好地管理零部件&#xff0c;下面我們一起來看看零部件概念及分類。1、按行業屬性分類&#xff08;1&#xf…

鍵盤忍者:使用單個熱鍵彈出Vista日歷

We’ve covered how to access the Windows Vista Calendar using the keyboard, but what if you wanted to assign a single keystroke to pop up the calendar? Yeah, sure, you can just click it with the mouse, but where’s the geek fun in that? 我們已經介紹了如何…

Linux下全局安裝composer方法

# 下載composer [vagrantlocalhost ~]$ curl -sS https://getcomposer.org/installer | php# 將composer.phar文件移動到bin目錄以便全局使用composer命令 [vagrantlocalhost ~]$ mv composer.phar /usr/local/bin/composer# 切換國內源 [vagrantlocalhost ~]$ composer config…

如何使用必應地圖 WPF 控件

如何使用必應地圖 WPF 控件如何使用必應地圖 WPF 控件作者&#xff1a;WPFDevelopersOrg - 驚鏵原文鏈接&#xff1a;https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用.NET40&#xff1b;Visual Studio 2019;Bing Maps WPF 控件需要 .NET Framework 4.0和 Windows S…

如何保存推特鏈接以供以后從臺式機和手機閱讀

Have you come across a lot of interesting links from Twitter, but you don’t have the time to read all of them? Today we’ll show you how to read these links later from your desktop and phone. 您是否遇到過Twitter上很多有趣的鏈接&#xff0c;但沒有時間閱讀所…

scrapy爬蟲實戰分享

自動登錄腳本參考scrapy爬蟲啟示錄-小伙子老夫看你血氣方剛這本《爬蟲秘錄》就傳給你了Scrapy初章-Scrapy理論簡介Scrapy次章-啥也不干就是爬圖Scrapy第四章-設置代理IP偷偷爬圖Scrapy第三章-圖片存庫MysqlScrapy第五章-多線程加速爬圖Scrapy終章-1024福利Scrapy最最最終章-摟一…

【重大更新】DevExpress v17.2新版亮點—Bootstrap篇(二)

用戶界面套包DevExpress v17.2日前終于正式發布&#xff0c;本站將以連載的形式為大家介紹各版本新增內容。本文將介紹了Bootstrap Controls v17.2 的CardView、Charts、Editors、GridView、Layout等新功能&#xff0c;快來下載試用新版本&#xff01; GridView Toolbar 在此版…

盤點 .NET 7 新功能

點擊上方藍字關注我們&#xff08;本文閱讀時間&#xff1a;20分鐘)本文翻譯于 Jeremy Likness, Angelos Petropoulos 和 Jon Douglas 的博客.NET 7 為C# 11/F# 7、.NET MAUI、ASP.NET Core/Blazor、Web API、WinForms、WPF 等應用程序帶來了更高的性能和新功能。使用 .NET 7&a…

onlyoffice采坑筆記

中文版onlyoffice/documentserver鏡像制作onlyoffice 20并發限制處理&#xff0c;up to 20 maximumonlyoffice安裝-Linuxwindows 10 下用docker安裝onlyoffice服務 onlyoffice安裝-Linux 0 點贊 ? 0 回復 ? 3月前onlyoffice相關命令記錄 0 點贊 ? 0 回復 ? 3月前onlyoffice…