首頁 後端開發 C#.Net教程 .net垃圾回收(GC)原理

.net垃圾回收(GC)原理

Nov 26, 2016 am 10:22 AM
.net 垃圾回收

作為.NET進階內容的一部分,垃圾回收器(簡稱GC)是必須了解的內容。本著「簡單易懂」的原則,本文將說明CLR中垃圾回收器的工作原理。

基礎知識

託管堆(Managed Heap)

先來看MSDN的解釋:初始化新進程時,運行時會為進程保留一個連續的位址空間區域。這個保留的位址空間稱為託管堆。

“託管堆也是堆”,為什麼這樣說呢?這麼說是希望大家不要被「術語」迷惑,這個知識點的前提是「值類型和引用類型的區別」。這裡假設讀者已經知道「值型別儲存在堆疊中,參考型別儲存在堆中。(引用型別的參考儲存在堆疊中)」這個重要概念。所以,根據這個理論,除值類型外,CLR要求所有資源都從託管堆分配。

託管堆維護一個指針,這裡命名為NextObjPtr,它指向下一個物件在堆中的分配位置。

.net垃圾回收(GC)原理

CPU暫存器(CPU Register)

這個是電腦基礎知識,這裡複習一下,有助於對下面「根」概念的理解。

CPU暫存器是CPU自己的”臨時記憶體”,比記憶體的存取還快。按與CPU遠近來分,離得最近的是暫存器,然後快取(電腦一、二、三級快取),最後記憶體。

根(Roots)

類別中定義的任何靜態字段,方法的參數,局部變數(僅限引用型別變數)等都是根,另外cpu暫存器中的物件指標也是根。根是CLR在堆之外可以找到的各種入口點。

.net垃圾回收(GC)原理

對象可達與不可達(Objects reachable and unreachable)

如果一個根引用了堆中的一個對象,則該對象為“可達”,否則即是“不可達”。

垃圾回收的原因

從電腦組成的角度來講,所有的程式都是要駐留在記憶體中運作的。而記憶體是一個限制因素(大小)。除此之外,託管堆也有大小限制。如果託管堆沒有大小限制,那麼C#的執行速度要優於c了(託管堆的結構讓它有比c運行時堆更快的物件分配速度)。因為位址空間和儲存的限制因素,託管堆要通過垃圾回收機制,來維持它的正常運作,確保物件的分配,不會「記憶體溢出」。

垃圾回收的基本原理

回收分為兩個階段:  標記 –> 壓縮

標記的過程,其實就是判斷物件是否可達的過程。當所有的根都檢查完畢後,堆中將包含可達(已標記)與不可達(未標記)物件。

標記完成後,進入壓縮階段。在這個階段中,垃圾回收器線性的遍歷堆,以尋找不可達物件的連續記憶體區塊。並把可達物件移動到這裡以壓縮堆。這個過程有點類似磁碟空間的碎片整理。

.net垃圾回收(GC)原理

如上圖所示,綠色框表示可達對象,黃色框為不可達對象。不可達到物件清除後,移動可達物件實現記憶體壓縮(變得更緊湊)。

壓縮之後,「指向這些物件的指標」的變數和CPU暫存器現在都會失效,垃圾回收器必須重新存取所有根,並修改它們來指向物件的新記憶體位置。這會造成顯著的效能損失。這個損失也是託管堆的主要缺點。

基於上述特點,垃圾回收引發的回收演算法也是一項研究主題。因為如果真等到託管堆滿才開始執行垃圾回收,那就真的太「慢」了。

垃圾回收演算法 – 分代(Generation)演算法

代是CLR垃圾回收器採用的一種機制,它唯一的目的就是提升應用程式的效能。分代回收,速度顯然快於回收整個堆。

CLR託管堆支援3代:第0代,第1代,第2代。第0代的空間約256KB,第1代約2M,第2代約10M。新構造的物件會被分配到第0代,

.net垃圾回收(GC)原理

如上圖所示,當第0代的空間滿時,垃圾回收器啟動回收,不可達物件(上圖C、E)會被回收,存活的對像被歸為第1代。

.net垃圾回收(GC)原理

當第0代空間已滿,第1代也開始有很多不可達對像以至空間將滿時,這時兩代垃圾都將被回收。存活下來的對象(可達對象),第0代升為第1代,第1代升為第2代。

實際CLR的代回收機制更加“智能”,如果新創建的對像生存週期很短,第0代垃圾也會立刻被垃圾回收器回收(不用等空間分配滿)。另外,如果回收了第0代,發現還有很多物件“可達”,

並沒有釋放多少內存,就會增大第0代的預算至512KB,回收效果就會轉變為:垃圾回收的次數將減少,但每次都會回收大量的記憶體。如果還沒有釋放多少內存,垃圾回收器將執行

完全回收(3代),如果還是不夠,則會拋出“內存溢出”異常。

也就是說,垃圾回收器會根據回收記憶體的大小,動態的調整每一代的分配空間預算!達到自動優化!

總結

垃圾回收背後有這樣一個基本的觀念:程式語言(大多數的)似乎總是能存取無限的記憶體。而開發者可以一直分配、分配再分配──像魔法一樣,取之不盡用之不竭。

.NET垃圾回收器的基本工作原理是:透過最基本的標記清除原理,清除不可達物件;再像磁碟碎片整理一樣壓縮、整理可用記憶體;最後透過分代演算法實現效能最優化。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
C#常見的記憶體管理問題及解決方法 C#常見的記憶體管理問題及解決方法 Oct 11, 2023 am 09:21 AM

C#中常見的記憶體管理問題及解決方法,需要具體程式碼範例在C#開發中,記憶體管理是一個重要的問題,不正確的記憶體管理可能會導致記憶體洩漏和效能問題。本文將向讀者介紹C#中常見的記憶體管理問題,並提供解決方法,並給出具體的程式碼範例。希望能幫助讀者更理解和掌握記憶體管理技術。垃圾回收器不及時釋放資源C#中的垃圾回收器(GarbageCollector)負責自動釋放不再使

C#開發中如何避免記憶體洩漏 C#開發中如何避免記憶體洩漏 Oct 08, 2023 am 09:36 AM

C#開發中如何避免記憶體洩漏,需要具體程式碼範例記憶體洩漏是軟體開發過程中常見的問題之一,特別是在使用C#語言進行開發時。記憶體洩漏會導致應用程式佔用越來越多的記憶體空間,最終導致程式運行緩慢甚至崩潰。為了避免記憶體洩漏,我們需要注意一些常見的問題並採取相應措施。及時釋放資源在C#中,使用完資源後一定要及時釋放它們,尤其是涉及文件操作、資料庫連線和網路請求等資源。可以

分享幾個.NET開源的AI和LLM相關專案框架 分享幾個.NET開源的AI和LLM相關專案框架 May 06, 2024 pm 04:43 PM

當今人工智慧(AI)技術的發展如火如荼,它們在各個領域都展現了巨大的潛力和影響力。今天大姚給大家分享4個.NET開源的AI模型LLM相關的專案框架,希望能為大家提供一些參考。 https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一種開源的軟體開發工具包(SDK),旨在將大型語言模型(LLM)如OpenAI、Azure

Java 函數中記憶體管理技術與安全性的關係是什麼? Java 函數中記憶體管理技術與安全性的關係是什麼? May 02, 2024 pm 01:06 PM

Java中的記憶體管理涉及自動記憶體管理,使用垃圾回收和引用計數來分配、使用和回收記憶體。有效的記憶體管理對於安全性至關重要,因為它可以防止緩衝區溢位、野指標和記憶體洩漏,從而提高程式的安全性。例如,透過正確釋放不再需要的對象,可以避免記憶體洩漏,從而提高程式效能並防止崩潰。

C#的就業前景如何 C#的就業前景如何 Oct 19, 2023 am 11:02 AM

無論您是初學者還是有經驗的專業人士,掌握C#將為您的職業發展鋪平道路。

Python開發中遇到的記憶體管理問題及解決方案 Python開發中遇到的記憶體管理問題及解決方案 Oct 09, 2023 pm 09:36 PM

Python開發中遇到的記憶體管理問題及解決方案摘要:在Python開發過程中,記憶體管理是一個重要的問題。本文將討論一些常見的記憶體管理問題,並介紹相應的解決方案,包括引用計數、垃圾回收機制、記憶體分配、記憶體洩漏等。並提供了具體的程式碼範例來幫助讀者更好地理解和應對這些問題。引用計數Python使用引用計數來管理記憶體。引用計數是一種簡單而有效率的記憶體管理方式,它記錄每

如何使用Go語言進行記憶體優化與垃圾回收 如何使用Go語言進行記憶體優化與垃圾回收 Sep 29, 2023 pm 05:37 PM

如何使用Go語言進行內存優化與垃圾回收Go語言作為一門高效能、並發、效率高的程式語言,對於內存的優化和垃圾回收有著很好的支援。在開發Go程式時,合理地管理和最佳化記憶體使用,能夠提高程式的效能和可靠性。使用適當的資料結構在Go語言中,選擇合適的資料結構對記憶體的使用有很大的影響。例如,對於需要頻繁新增和刪除元素的集合,使用鍊錶代替陣列可以減少記憶體碎片的產生。另外,

Python底層技術解析:如何實作垃圾回收機制 Python底層技術解析:如何實作垃圾回收機制 Nov 08, 2023 pm 07:28 PM

Python底層技術解析:如何實現垃圾回收機制,需要具體程式碼範例引言:Python作為一種高階程式語言在開發中極為方便且靈活,但是其底層實作卻是相當複雜的。本文將聚焦在Python的垃圾回收機制,包括垃圾回收的原理、演算法以及具體的實作程式碼範例。希望透過本文對Python垃圾回收機制的解析,讀者能夠更深入了解Python底層技術。一、垃圾回收原理首先,我

See all articles