垃圾回收

来源:https://www.cnblogs.com/TimLiuDream/archive/2022/10/09/16774015.html
-Advertisement-
Play Games

垃圾回收器 垃圾回收是釋放掉那些不再被使用的記憶體空間的過程。 換句話說,垃圾回收器會去檢查哪些對象超出範圍並且不會再被引用到,然後它回去釋放掉那些對象占用的記憶體空間。這個過程實在 go 程式運行中以併發的方式去進行的,不是 go 程式執行之前,也不是 go 程式執行之後。go 垃圾回收器實現的說明文 ...


垃圾回收器

垃圾回收是釋放掉那些不再被使用的記憶體空間的過程。

換句話說,垃圾回收器會去檢查哪些對象超出範圍並且不會再被引用到,然後它回去釋放掉那些對象占用的記憶體空間。這個過程實在 go 程式運行中以併發的方式去進行的,不是 go 程式執行之前,也不是 go 程式執行之後。go 垃圾回收器實現的說明文檔給出瞭如下聲明(runtime 包下的 mgc.go):

The GC runs concurrently with mutator threads, is type accurate (aka

precise), allows multiple GC thread to run in parallel. It is a concurrent

mark and sweep that uses a write barrier. It is non-generational and non

compacting. Allocation is done using size segregated per P allocation

areas to minimize fragmentation while eliminating locks in the common

case.

垃圾回收是和go線程同時運行的,它是類型精確的,而且多個垃圾回收線

程可以並行運行。它是一種使用了寫屏障的併發標記清除的垃圾回收方

式。它是非分代和非壓縮的。使用按P分配區域隔離的大小來完成分配,

以最小化碎片,同時消除常見情況下的鎖。

三色演算法

go垃圾回收器的操作都是基於三色演算法。

嚴格來說,在Go中這個演算法的官方名稱是叫做三色標記清除演算法(tricolor mark-and-sweep algorithm)。它可以和程式一起併發工作並且使用寫屏障(write barrier)。這就意味著,當Go程式員運行起來,go調度器去負責應用程式的調度,而垃圾回收器會像調度器處理常規應用程式一樣,去使用多個goroutines去進行工作。

三色標記清除演算法背後的首要原則就是它把堆中的對象根據它們的顏色分到不同集合裡面,顏色是根據演算法進行標記的。

黑色集合是為了確保沒有任何指針指向白色集合。但是白色集合中的對象允許有指針指向黑色集合,因為這不會對垃圾回收器的操作產生影響。灰色集合可能會有指針指向白色集合里的對象。白色集合中的對象就是垃圾回收的候選對象。

註意到沒有任何對象可以從黑色集合進到白色集合,這允許演算法能夠去操作並且清除白色集合里的對象。此外,沒有任何黑色集合里的指針對象能夠直接指向白色集合中的對象。

當垃圾回收開始,全部對象標記為白色,然後垃圾回收器會遍歷所有根對象並把它們標記為灰色。根對象就是程式能直接訪問到的對象,包括全局變數以及棧裡面的東西。這些對象大多數取決於特定程式的go代碼。在這之後,垃圾回收器選取一個灰色的對象,把它變為黑色,然後開始尋找去確定這個對象是否有指針指向白色集合的對象。這意味著當一個灰色對象由於被其它對象的指針所指而掃描到的時候,這個灰色對象會被標記為黑色。如果掃描發現這個灰色對象有一個或者更多指針指向白色對象時,會把所指向的白色對象放到灰色集合里。只要有灰色集合對象存在,這個過程就會一直進行下去。之後,白色集合里的對象就是沒人訪問的對象,並且它們所占用的記憶體可以被回收重用。因此,在這個點上,我們說白色集合里的元素被垃圾回收了。

在這個過程中,運行應用程式被叫做修改器(mutator)。mutator去運行一個小的方法叫做寫屏障**(write barrier)**,每次堆中的指針被修改寫屏障都會去執行。如果堆中對象的指針被修改,就意味著那個對象現在是可觸達的,寫屏障會把它標記為灰色並把它放到灰色集合中。

mutator負責保持黑色集合中沒有任何元素的指針去指向白色集合中的元素。這是在寫屏障方法的幫助下完成的。如果維持這個不變狀態失敗的話,會毀壞垃圾回收過程,並且很可能會以一種醜陋和非預期的方式破壞你的程式。

go垃圾回收也可以應用於其它變數例如channel!當垃圾回收器發現一個channel是不可達的而且channel變數再也不會被訪問到,它就會釋放掉它的資源甚至說channel還沒被關閉!

Go允許你通過在你的Go代碼里放一個 runtime.GC() 的聲明來手動去開啟一次垃圾回收。但是,要記住一點, runtime.GC() 會阻塞調用器,並且它可能會阻塞整個程式,尤其是如果你想運行一個非常繁忙的而且有很多對象的go程式。這種情況發生,主要是因為你不能在其他任何事都在頻繁變化的時候去處理垃圾回收,因為這種情況不會給垃圾回收器機會,去清楚地確定白色、黑色和灰色集合里的成員。這種垃圾回收狀態也被稱作是垃圾回收安全點**(garbage collection safe-point)**。

垃圾回收器背後的更多操作

go垃圾回收器的主要關註點是低延遲,也就是說為了進行實時操作它會有短暫的暫停。另一方面,創建新對象然後使用指針操作存活對象是程式始終在做的事情,這個過程可能最終會創建出不會再被訪問到的對象,因為沒有指向那些對象的指針。這種對象即為垃圾對象,它們等待被垃圾回收器清理然後釋放它們的空間。之後它們釋放的空間可以再次被使用。

垃圾回收中使用的最簡單的演算法就是經典的標記清除演算法**(mark-and sweep)**:演算法為了遍歷和標記堆中所有可觸達對象,會把程式停下來(stop the world)。之後,它會去清掃(sweeps)不可觸達的對象。在演算法的標記(mark)階段,每個對象被標記為白色、灰色或黑色。灰色的子對象標記為灰色,而原始的對象此時會標記為黑色。沒有更多灰色對象去檢查的話就會開始清掃階段。這個技術適用是因為沒有從黑色指向白色的指針,這是演算法的基本不變要素。

儘管標記清除演算法很簡單,但是它會暫停程式的運行,這意味著實際過程中它會增加延遲。go會通過把垃圾回收器作為一個併發的處理過程,同時使用前一節講的三色演算法,來降低這種延遲。但是,在垃圾回收器併發運行時候,其它的過程可能會移動指針或者創建對象,這會讓垃圾回收器處理非常困難。所以,讓三色演算法併發運行的關鍵點就是,維持標記清除演算法的不變要素即沒有黑色的對象能夠指向白色集合對象。

因此,新對象必須進入到灰色集合,因為這種方式下標記清除的不變要素不會被改變。另外,當程式的一個指針移動,要把指針所指的對象標記為灰色。你可以說灰色集合是白色集合和黑色集合中間的“屏障”。最後,每次一個指針移動,會自動執行一些代碼,也就是我們之前提到的寫屏障,它會去進行重新標色。為了能夠併發運行垃圾回收器,寫屏障代碼產生的延遲是必要的代價。

一定要記住,Go垃圾回收器是一個實時的垃圾回收器 ,它是和其他goroutines一起併發運行的

還在找我的道
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 導讀:成為一名架構師可能是很多開發者的技術追求之一。那麼如何理解架構?架構師是一個什麼樣的角色,需要具備什麼樣的能力?在架構師的道路上,會面臨哪些挑戰?本文作者道延分享他對架構以及架構師的思考和相關實踐,希望對同學們有所啟發。 ...
  • 定義抽象基類,規範介面內部方法執行順序 在進階篇中,沒專門提過抽象基類,在這裡順便就提一下 抽象基類的核心特征:不能被直接實例化 相反,抽象基類和元類一樣,一般都被當做頂層基類使用,派生類必須實現抽象類中指定的方法,且方法名也必須保持一致 抽象基類的主要用途:從一種高層次上規範編程介面 話不多說,直 ...
  • 本文詳細介紹了我國銀行核心系統的定義、位置與邊界,發展歷程、更換核心系統的原因,以及新核心建設的五大模式與其特點對比。希望內容能夠幫助銀行科技從業者建立起對銀行核心系統的整體認知,提供一定積極的指導作用與借鑒意義,從而引發思考並促進行業交流與探討,共同為我國的銀行科技蓬勃發展貢獻自己的智慧與經驗。 ... ...
  • 外觀模式是最常用的結構型設計模式,也是一種非常容易理解的設計模式,其核心就是為多個子系統提供一個統一的介面,將這個介面看作是這些子系統的門面。 ...
  • 上次說了一下Go語言佈道師 Dave Cheney對Go併發的建議,個人覺得最重要的一條,這次主要想說一下這個。 8.3. Never start a goroutine without knowning when it will stop(永遠不要在不知道何時停止的情況下啟動 goroutine) ...
  • Future模式 【1】Future模式是多線程開發中常見的設計模式,它的核心思想是非同步調用。對於Future模式來說,它無法立即返回你需要的數據,但是它會返回一個契約,將來你可以憑藉這個契約去獲取你需要的信息。 【2】通俗一點就是生產者-消費者模型的擴展。經典“生產者-消費者”模型中消息的生產者不 ...
  • stream是java8新出的抽象概念,他可以讓你根據你期望的方式來處理集合數據,能夠輕鬆的執行複雜的查找、過濾和映射數據等操作。Stream 使用一種類似用 SQL 語句從資料庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。 ...
  • 數據結構基礎—棧和隊列 一、棧和隊列的基本概念和性質 棧和隊列都是特殊的線性表 對他們的操作有著規定和限制:在插入和刪除時只能對某一端操作 棧:只能在一端進行(先進後出) 隊列:只能在表尾插入,在表頭刪除(先進先出) 二、棧 表頭為棧底,表尾為棧頂 1.棧的基本操作和規則 a.進棧和出棧 進棧:棧頂 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...