.NET GC工作流程

前言

在上文[如何獲取GC的STW時間]一文中,我們聊到了如何通過監聽GC發出的診斷事件來計算STW時間。里面只簡單的介紹了幾種GC事件和它的流程。
群里就有小伙伴在問,那么GC事件是什么時候產生的?分別是代表什么含義?
那么在本文就通過幾個圖為大家解答一下這個問題。

有哪些GC模式?

工作站和服務器模式

在.NET中,GC其實有一些不同的工作模式,根據客戶端和服務器可以分為如下兩種模式:

Workstation GC

Workstation GC(工作站GC),這種模式主要是為了滿足基于UI的交互式應用程序設計的,交互式意味著GC的暫停時間要盡可能的短。因為我們不想因為觸發GC導致較長的GC停頓。

  • GC會更頻繁的發生,每次暫停時間都會很短。

  • 內存占用率更低,因為GC更頻繁的發生,所以內存回收的更積極,占用率也會更低。

  • 無論是否有配置多CPU核心,垃圾回收始終只使用一個CPU核心,只有一個托管堆。

  • 內存段的大小設置會很小。

Server GC

Server GC (服務器GC),這種模式主要是為了滿足基于請求處理的WEB等類型應用程序設計的,這意味著它更側重于需要滿足大的吞吐量,零星的停頓不會對齊產生重大的影響。

  • GC的發生頻率會降低,優先滿足大吞吐量。

  • 內存占用率會更高,因為GC發生的頻率變低,內存中可能會有很多垃圾對象。

  • 垃圾回收使用高優先級運行在多個專用線程上。每個CPU核心都提供執行垃圾回收的專用線程和堆,每個CPU核心上的堆都包含小對象、大對象堆。

  • 因為多個垃圾回收線程一起工作,所以對于相同大小的堆,Server GC會回收的更快一些。

  • 服務器垃圾回收通常會有更大的Segment,另外也會占用更多的資源。

并發與非并發模式

另外根據GC相對于用戶線程的操作方式,還可以分為下面兩種方式:

Non-Concurrent

Non-Concurrent(非并發GC),這種方式是一直存在于.NET中的,它適用于工作站和服務器模式,在GC進行過程中,所有的用戶線程都會掛起

Concurrent(已過時)

Concurrent (并發GC),并發GC模式它和用戶線程同時工作,GC進行過程中只有少數幾個過程需要掛起用戶線程。所以它的實現也更加復雜,但是暫停時間會更短,性能也會更好,不過現在它已經過時,本文不會著重描述它。

Background

Background(后臺GC),在.NET Framework 4.0以后,后臺GC取代了并發GC,它只適用于Gen2的回收,但是它可以觸發對于Gen0、Gen1的回收。根據WorkstationGC和ServerGC的模式會分別在一個或多個線程上執行。

GC工作流程

需要知道的GC事件

其實對于我們分析GC的工作來說,上文中提到的幾個事件已經足夠使用了,讓我們再來回顧一下這些事件。

Microsoft-Windows-DotNETRuntime/GC/SuspendEEStart	//開始暫停托管線程運行Microsoft-Windows-DotNETRuntime/GC/SuspendEEStop	//暫停托管線程完成Microsoft-Windows-DotNETRuntime/GC/Start	// GC開始回收Microsoft-Windows-DotNETRuntime/GC/Stop		// GC回收結束Microsoft-Windows-DotNETRuntime/GC/RestartEEStart	//恢復之前暫停的托管線程Microsoft-Windows-DotNETRuntime/GC/RestartEEStop	//恢復托管線程運行完成

圖例

為了讓大家能更清晰的看懂下面的圖,會用不同形狀和顏色的圖像來代表不同的含義,如下方所示:

fb61f247f17318aee6d5803ea73c34e8.png

綠色:正在運行的用戶線程。
紅色:執行引擎進行線程凍結或線程恢復。
實線箭頭:正在運行的GC線程。
虛線箭頭:被暫停的線程。
黃色圓球:GC事件。
紅色圓球:標記點。

WorkstationGC模式-非后臺(并發)GC

下圖是WorkStationGC(非后臺)模式的執行流程,我們假設它是在一個雙核的機器上運行(下文中都是假設在雙核機器上運行),運行過程其實就像下圖所示。

72330904cf45db96782eda30bf20c699.png

在上圖中的事件流如下所示:

  1. GC/SuspendEEStart

  2. GC/SuspendEEStop

  3. GC/Start

  4. GC/Stop

  5. GC/RestartEEStart

  6. GC/RestartEEStop

其中各個標記點分別完成了如下工作:

  • A->B:暫停所有用戶線程

  • B->C: 挑選一個用戶線程作為GC線程,然后開始進行垃圾回收

    • 選擇-需要被回收的一代

    • 標記-被回收的一代和更年輕一代對象

    • 計劃-GC決定是需要壓縮整理堆還是只是清掃堆就夠了

    • 清掃、搬遷和壓縮-根據上面計劃的結果,執行清掃堆,或者搬遷活著的對象然后整理堆,最后所有對象的地址更新到新地址。

  • C->D: GC工作結束,恢復線程運行
    由于GC暫停了所有的線程,所以A->D就是此類GC的STW Time時間。

ServerGC模式-非后臺(并發)GC

下圖是ServerGC(非后臺)模式的執行流程。
7d21e7ebddff17d8cdc6d5c1491afb9a.png

它與WorkstationGC模式的事件流和完成的工作都一致,唯一不同的就是它會根據當前的CPU邏輯核心數量創建單獨的GC線程,比如上圖就有2個GC線程。
另外在服務器GC模式中,用戶線程還是可以作為GC線程來使用的,像用戶線程1在GC發生的時候就做了一些GC工作。

WorkstationGC模式-后臺GC

下圖是WorkstationGC(后臺)模式的執行流程,可以看到后臺模式還是相當復雜的,會短暫的暫停多次,每一次都會執行不同的操作。
ff6df21432a3c3519380a8ee42592f9c.png
除了工作線程GC以外,另外會有單獨的后臺GC線程進行后臺垃圾回收。
上圖中的事件流如下所示:

  1. GC/SuspendEEStart

  2. GC/SuspendEEStop

  3. GC/Start

  4. GC/RestartEEStart

  5. GC/RestartEEStop

  6. GC/SuspendEEStart

  7. GC/SuspendEEStop

  8. GC/RestartEEStart

  9. GC/RestartEEStop

  10. GC/SuspendEEStart

  11. GC/SuspendEEStop

  12. GC/Start

  13. GC/Stop

  14. GC/RestartEEStart

  15. GC/RestartEEStop

  16. GC/Stop

其中各個標記點完成的工作如下所示:

  • A->B:初始選擇、標記

    • 此時用戶線程是暫停的

    • 選擇需要被回收的一代

    • 找到GC roots,以便并發標記

  • B->C:并發標記

    • 此時用戶線程是正常運行的

    • 從上一步中找到的GC roots開始標記需要被回收的一代和年輕的代

  • D->E:最終標記

    • 此時用戶線程是暫停的

    • 掃描在并發標記過頁面,看看是否有修改讓對象重新活過來的

  • F->G:清掃小對象堆

    • 此時用戶線程是正常運行的

    • 清掃小對象堆的對象

  • H->I:壓縮整理小對象堆、清掃壓縮整理大對象堆

    • 此時用戶線程是暫停的

    • 選擇了一個用戶線程進行GC

    • 用來壓縮小對象堆的對象

    • 另外也會壓縮和整理大對象堆對象

  • J->K:清掃大對象堆

    • 此時用戶線程是正常運行的

    • 此時會清掃和整理大的對象堆

    • 此時會禁止分配大對象,阻塞對應線程直到大對象堆回收完成

從上面的的流程中可以看到,后臺GC主要是通過并發+多次短暫暫停來實現提升吞吐量和降低總體的STW Time的,其內部實現是非常復雜的,有興趣的小伙伴可以直接看dotnet/runtime/gc.cpp文件。

ServerGC模式-非后臺GC

下圖是ServerGC(后臺)模式的執行流程。
696cca275c1d665b038dc3cbaa8008f0.png
它與WorkstationGC模式的事件流和完成的工作都一致,唯一不同的就是它會根據當前的CPU邏輯核心數量創建單獨的GC線程,比如上圖就有2個GC線程,2個后臺GC線程。

總結

今天帶了解了一下.NET GC中的各個階段和事件的順序,當然這里只是簡單的帶大家了解一下,要知道在任何有runtime的平臺中,GC是其中相當關鍵的東西,大家如果對GC感興趣,可以閱讀附錄中的資料。

附錄

  • https://docs.microsoft.com/zh-cn/dotnet/standard/garbage-collection/

  • https://github.com/dotnet/runtime/blob/main/src/coreclr/gc/gc.cpp

  • https://netcoreimpl.github.io/

  • http://www.tup.tsinghua.edu.cn/booksCenter/book_08454701.html

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

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

相關文章

libco協程庫源碼解讀

2019獨角獸企業重金招聘Python工程師標準>>> 協程,又被稱為用戶級線程,是在應用層被調度,可以減少因為調用系統調用而阻塞的線程切換的時間.目前有很多協程的實現,由于微信內部大量使用了其直研的的libco協程庫,所以我選擇了騰訊開源的libco協程庫進行研…

【ArcGIS風暴】如何將矢量數據(點、線、面)折點坐標轉為GeoJSON格式?

本文以案例的形式,講述在ArcGIS和QGIS專業軟件中,將矢量數據轉為GeoJSON的方法。 擴展閱讀:【GIS風暴】GeoJSON數據格式案例全解 文章目錄 一、ArcGIS將矢量數據轉為GeoJSON二、QGIS將矢量數據轉為GeoJSON一、ArcGIS將矢量數據轉為GeoJSON ArcGIS中提供的【要素轉JSON】工具…

TypeScript 3.9 正式發布!平均編譯時長從 26 秒縮短至 10 秒

作者 | 微軟官方博客 譯者 | 核子可樂 策劃 | 小智 稿源 | 前端之巔 今天,微軟在其官方博客宣布:TypeScript 3.9 版本已經正式發布,詳情見下文。 有些朋友可能對 TypeScript 還不太熟悉,這是一種以 JavaScript 為基礎開發的語…

(二)Harbor WEB的使用

接上一篇《安裝Harbor》,安裝好之后,接下來我們就進行Harbor web界面的操作吧! 轉載請標明出處:http://www.cnblogs.com/huangjc/p/6270405.html 瀏覽器登陸Harbor(默認用戶密碼:admin/Harbor12345&#x…

iVX低代碼平臺系列制作簡單的登錄界面

一、前言 iVX是啥,不理解的小伙伴可以猛戳這里 ----------------------點我 二、iVX平臺和現有編程語言的對比 三、iVX平臺和現有編程語言的對比 1、快速學習(周期短) iVX邏輯上相對是比較簡單的 所以初學者的話只需要從邏輯和具體功…

【CASS精品教程】CASS9.1等高線的繪制完整案例教程

在地形圖中,等高線是表示地貌起伏的一種最重要的手段。在CASS成圖時,可自動生成精度高的等高線,本文講解CASS9.1生成等高線的完整操作流程。 文章目錄 1. 展高程點2. 建立數字地面模型3. 修改數字地面模型4. 繪制等高線5. 等高線的修飾6. 繪制三維模型擴展閱讀: ArcGIS實驗…

Process.Start 為什么會引發“系統找不到指定的文件”異常

前言偶然發現,如果想用如下代碼在 .NET 6 中打開指定 URL:Process.Start("https://baidu.com");會引發異常:而同樣的代碼在 .NET Framework 中是可以正常執行的。難道,.NET 6 下的實現邏輯不一樣?深入探究通…

JVM 類型的生命周期學習

Java虛擬機通過裝載、連接和初始化一個JAVA類型,使該類型可以被正在運行的JAVA程序所使用,其中,裝載就是把二進制形式的JAVA類型讀入JAVA虛擬機中;而連接就是把這種讀入虛擬機的二進制形式的類型數據合并到虛擬機的運行時狀態中去…

js對象數組中的某屬性值 拼接成字符串

var arr[{id: "600", pId: null, name: "圖形的變化"},{id: "630", pId: "600", name: "投影與視圖"},{id: "631", pId: "630", name: "投影"},{id: "632", pId: "630",…

898A. Rounding#數的舍入

題目出處&#xff1a;http://codeforces.com/problemset/problem/898/A 題目大意&#xff1a;找一個數最近的整十的數 #include<iostream> using namespace std; int main(){int a,b;cin>>a;ba;while(1){if(a%100){cout<<a<<endl;return 0;}if(b%100){…

開店星簡直就是國內優秀的開源商城系統天花板

一、場景 1、大學生畢業設計做商城系統背景 好家伙、又到開學季節了&#xff0c;師妹讓我幫忙給指導大四的項目&#xff0c;作為畢業設計和為后面找工作積累項目經驗&#xff0c;要搞一個買賣二手閑置品的商城小程序和PC端商城、希望能夠快速學習、接入、修改部分功能&#xff…

【CASS精品教程】CASS9.1土方量的計算方法匯總

CASS9.1中,計算土方量的方法有:DTM法土方計算、斷面法進行土方量計算、方格網法土方計算、等高線法土方計算、區域土方量平衡等。本文以案例的形式,詳細講解土方量的計算過程。 文章目錄 一、DTM法土方計算二、斷面法進行土方量計算三、方格網法土方計算四、等高線法土方計算…

html標簽缺省(自帶)樣式大全

html標簽默認樣式整理 作者&#xff1a;佚名 來源&#xff1a;互聯網 時間&#xff1a;07-30 16:54:48 文為大家整理了html標簽默認樣式屬性及瀏覽器默認樣式等等&#xff0c;喜歡css布局的朋友們可以學下&#xff0c;希望對大家有所幫助html, address,blockquote,body, dd, …

VS2019 禁止Web項目停止調試后自動關閉瀏覽器(在瀏覽器窗口關閉時停止調試程序,在調試停止時關閉瀏覽器)

很多文章都說要修改以下兩處與“編輯并繼續”有關的選項&#xff1a; “編輯并繼續”是一種省時的功能&#xff0c;使你能夠在程序處于中斷模式時更改源代碼。 通過選擇執行命令&#xff08;如 "繼續" 或 "單步執行"&#xff09;繼續執行程序時&#xff0c…

iOS - block變量捕獲原理

block對變量的捕獲 1&#xff1a;可以捕獲不可以修改變量 局部變量2&#xff1a;可以捕獲且可以修改變量 全局變量靜態變量__block修飾的局部變量原理分析&#xff1a; 1. 局部變量為什么可以被捕獲確不能修改 int a 10; void (^blcok)() [^{NSLog("%d",a); } copy…

Shell 更好看的回顯

#!/bin/shsource /etc/init.d/functionsaction "hello" /bin/true轉載于:https://blog.51cto.com/itech/1768218

【ArcGIS風暴】ArcGIS中等高線高程標注/注記(打斷/消隱)方法案例匯總

本文以案例的形式,圖文并茂詳細講解在ArcGIS 10.6中,等高線高程標注、注記的方法。 文章目錄 一、屬性標注二、Maplex工具標注1. 使用Maplex標注引擎2. 標注轉換為注記3. 要素輪廓線掩膜4. 使用掩膜選項進行繪制參考閱讀: 【CASS精品教程】CASS9.1等高線的繪制完整案例教程 …

Blazor University (35)表單 —— 編寫自定義驗證

原文鏈接&#xff1a;https://blazor-university.com/forms/writing-custom-validation/編寫自定義驗證源代碼[1]請注意&#xff0c;與有關 EditContext、FieldIdentifiers 和 FieldState[2] 的部分一樣&#xff0c;這是一個高級主題。如前所述&#xff0c;FieldState 類保存表…

HTML 元素內部添加預加載

CSS&#xff1a; /*元素內部加載loading*/.innerLoading {height: 100%;width: 100%;display: flex;justify-content: center;align-items: center;}.innerLoading * {text-align: center;color: #737782cc;fill: #73777A;font-size: 1em !important;font-family: SimSun,SimHe…

Windows下怎樣安裝Tomcat

Tomcat 是開源的WEB應用容器&#xff0c;所以受到各位程序員和公司的親賴。在這里給大家介紹一下如何在Windows環境下安裝Tomcat綠色版本&#xff0c;希望能夠對大家有幫助。 1.首先去Tomcat官網下載Tomcat軟件&#xff0c;在百度中搜索Tomcat,進入英文網址http://tomcat.apach…