Go 語言的 GC 垃圾回收

序言

?垃圾回收(Garbage Collection,簡稱 GC)機制 是一種自動內存管理技術,主要用于在程序運行時自動識別并釋放不再使用的內存空間,防止內存泄漏和不必要的資源浪費。這篇文章讓我們來看一下 Go 語言的垃圾回收機制是如何設計的吧。


一、為什么需要垃圾回收?

?熟悉 C/C++ 編程的同學肯定清楚自己手動管理內存的手段:

  • 分配內存:malloc, new
  • 釋放內存:free, delete

對待內存管理一定要小心謹慎,不然稍有疏漏就會引起以下嚴重的問題:

  • 忘記釋放內存 → 內存泄漏
  • 多次釋放同一塊內存 → 崩潰或未定義行為
  • 訪問已釋放的內存 → 懸空指針

所以說垃圾回收機制大大的提高了內存管理的下限,但是同時這是以一定的性能開銷換取的。


二、Go 垃圾回收機制

?我們現在看到的機制都是比較完善的,但是很多時候我們不明白他為什么要這么做,有什么好處?這是因為我們站在巨人的肩膀上,機制是在使用中不斷完善的。所以看事情不能只看現在,明白他大致來時候的路是必要的。

2.1 標記-清掃式垃圾回收(Mark-Sweep GC)

2.1.1 回收流程

?首先當前執行的邏輯暫停(也稱為 Stop-The-World STW),然后標記所有存活對象。從根對象(比如全局變量、當前棧中的局部變量等)開始遍歷所有被引用的對象,并將對象標記為存活狀態:
在這里插入圖片描述
現在標記的動作完成了,需要回收沒有被引用的空間了。遍歷整個堆的空間,然后對于沒有被標記的對象,釋放其內存:
在這里插入圖片描述
最后便是恢復程序的執行了,可以看出剛開始的機制還是比較簡單的。

2.1.2 Mark-Sweep 的缺點

?STW 時間長降低了程序的執行的效率。如果當前的程序對于空間的申請和釋放的操作比較頻繁時,執行時的卡頓感會愈發的強烈,因為 STW 這段時間程序是被阻塞的,無法正常運行。
?內存碎片化嚴重。清掃后會產生很多小塊的空閑內存,可能導致大對象無法分配,降低了內存的利用率。
?掃描整個堆。如果當前堆比較大的話,也會拉長 STW 的時間。

這個方式是在 Go V1.4 之前使用的,現在被替換了,但是作為一個引子還是不錯的。

2.2 三色并發垃圾回收(Tri-color Concurrent GC )

2.2.1 回收流程

?首先在每次創建新的對象的時候將該對象標記為 白色
在這里插入圖片描述
現在觸發 GC 了,從根節點遍歷,將該節點 root 指向的堆對象從 white 表 放入 grey 表,由于這里只有一個根對象,所以這里只需要處理 a
在這里插入圖片描述
根上的對象遍歷完成了,現在遍歷 grey 表 將節點 a 指向的對象也全放入 grey 表 ,同時將 a 放入 black 表 表示他的可達對象處理完成了:在這里插入圖片描述
之后重復第二部操作直至 grey 表 的數據為空:
在這里插入圖片描述
到最后我們發現 white 表 只剩下了一個不可達對象 f,這個就是需要回收的空間。縱觀整個過程,其實就是一個廣度遍歷來查找不可達對象的過程。
?比較現有的兩個機制,后者一個很大優點就是 不需要遍歷整個堆來查找不可達對象,因為最開始的時候就記錄了創建的每一個對象。但是我們這里好像少了些什么,不需要 STW 嗎?

2.2.2 假設沒有 STW

?就比如 e 其實是一個可達對象的,但是由于在執行回收的過程中當前的程序也在正常的執行,讓 de 斷開連接并讓一個新的根節點(比如局部變量)指向 e
在這里插入圖片描述
因為對根節點的遍歷只在最初執行一遍,后續不會再遍歷了導致錯誤地判定 e 為不可達對象釋放該空間,這不就錯誤地釋放空間了嗎(也稱為 漏標)。
?最直接的方式就是在回收的過程中加上 STW,但是這個方式的弊端上面也說過了。那怎么辦呢?減少 STW 的時間。

2.2.3 屏障機制
1. 強弱三色不變式

?由于程序的執行和垃圾回收的過程是并發的,就導致了錯誤地回收了某些還需要繼續使用的對象。為了避免這種情況,引入了 三色不變式
?強三色不變式,所有黑對象不能直接或間接引用白對象。也就是說:如果一個對象已經是黑色,它不能指向任何未被標記的白色對象。
?弱色不變式。所有白對象可以被黑色對象引用,但是這個白色對象必須存在著其他灰色對象對他的引用。

2. 插入寫屏障

滿足:強三色不變式
操作:當一個黑色對象引用一個白色對象之前,先將該白色對象修改為灰色對象,在建立引用:
在這里插入圖片描述
并且這里還有一個機制是 插入寫屏障只作用于堆對象。因為棧上的變量變更比較頻繁, 如果一變更我們就去執行插入寫屏障會非常的耽誤時間。作為補償,會在整體三色標記清除之后,專門對棧上的空間執行次三色標記掃描并加上 STW 保護。

3. 刪除寫屏障

滿足:弱三色不變式
操作:當一個白色對象被上游刪除引用時,會將將自己修改為灰色對象:
在這里插入圖片描述
這種方式其實也是延遲回收策略,當真正想刪除該對象時,這一輪他會存活下來,但是下一輪肯定會被帶走。

2.3.4 Tri-color Concurrent 的缺點

?這兩種方式任選一種即可解決漏標的問題,Go V1.8 及以前使用的是刪除寫屏障。該種方式的缺點是:

  • 回收精度偏低。本次 GC 過程中需要刪除的對象會在下一輪清除

而插入寫屏障的缺點也不小:

  • 會在結束時掃描整個棧,并且伴隨著 STW

那是否可以取長補短互相融合呢?

2.3 混合寫屏障機制(Hybrid Write Barrier)

?將棧上的對象掃描之后全部標記為 黑色,期間任何新增的對象標記為 灰色,任何被刪除的對象也標記為 灰色。這樣節省了掃描整個棧并伴隨的 STW 帶來的性能消耗。


三、總結

?現在縱觀大體的發展路線,你是否可以理解:混合寫屏障(Hybrid Write Barrier)是一種改進型寫屏障機制,它結合了 刪除寫屏障 和 插入寫屏障 的優點,在并發三色標記中有效地防止漏標問題,并顯著減少了 STW 時間。

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

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

相關文章

60天python訓練計劃----day45

DAY 45 Tensorboard使用介紹 知識點回顧: tensorboard的發展歷史和原理tensorboard的常見操作tensorboard在cifar上的實戰:MLP和CNN模型 之前的內容中,我們在神經網絡訓練中,為了幫助自己理解,借用了很多的組件&#x…

RocketMQ基礎概念的理解

1、生產者 生產者和主題之間存在多對多關系。一個生產者可以向多個主題發送消息,一個主題可以接收來自多個生產者的消息。這種多對多關系有助于提高性能擴展和災難恢復能力。 2、消費者以及消費者組 一個隊列可以被多個消費者(其中這多個消費者必須分…

Flash燒錄速度和加載配置速度(純FPGA ZYNQ)

在工程綜合完成或者implement完成后,打開綜合設計或者實現設計。 toots--->Edit Device Properties--->打開比特流設置 將bitstream進行壓縮 上圖中,時鐘頻率選擇的檔位有限,最大為66MHZ io的bus width可以設置為x1,x2,x4 vivado在設計…

優化09-表連接

一、表連接介紹 表連接類型 表連接是關系型數據庫關鍵特性,在關系型數據庫中,表連接分為三類:循環嵌套連接(Nested Loops Join)、哈希連接(Hash Join)、合并排序連接(Merge Sort J…

Dify工作流實踐—根據word需求文檔編寫測試用例到Excel中

前言 這篇文章依賴到的操作可查閱我之前的文章: dify里的大模型是怎么添加進來的:在Windows本地部署Dify詳細操作 flask 框架app.route()函數的開發和調用:PythonWeb開發框架—Flask工程創建和app.route使用詳解 結構化提示詞的編寫&…

AWTK 嵌入式Linux平臺實現多點觸控縮放旋轉以及觸點丟點問題解決

前言 最近涉及海圖的功能交互,多點觸摸又開始找麻煩。 在PC/Web平臺awtk是通過底層的sdl2庫來實現多點觸摸,但是在嵌入式Linux平臺,可能是考慮到性能原因,awtk并沒有采用sdl庫來做事件處理,而是自己實現一個awtk-lin…

Diffusion Planner:擴散模型重塑自動駕駛路徑規劃(ICLR‘25)

1. 概述 2025年2月14日,清華大學AIR智能產業研究院聯合毫末智行、中科院自動化所和香港中文大學團隊,在ICLR 2025會議上發布了Diffusion Planner——一種創新性的基于Diffusion Transformer的自動駕駛規劃模型架構。該系統聯合建模周車運動預測與自車行…

ESP32對接巴法云實現配網

目錄 序言準備工作巴法云注冊與使用Arduino準備 開發開始配網 序言 本文部分內容摘抄原創作者巴法云-做優秀的物聯網平臺 代碼有部分修改并測試運行正常 巴法云支持免費用戶通過開發對接實現各智能音箱設備語音控制智能家居設備,并有自己的App進行配網和控制&…

深度學習習題3

1.訓練神經網絡過程中,損失函數在一些時期(Epoch)不再減小, 原因可能是: 1.學習率太低 2.正則參數太大 3.卡在了局部最小值 A1 and 2 B. 2 and 3 C. 1 and 3 D. 都是 2.對于分類任務,我們不是將神經網絡中的隨機權重…

【EasyExcel】導出時添加頁眉頁腳

一、需求 使用 EasyExcel 導出時添加頁眉頁腳 二、添加頁眉頁腳的方法 通過配置WriteSheet或WriteTable對象來添加頁眉和頁腳。以下是具體實現步驟: 1. 創建自定義頁眉頁腳實現類 public class CustomFooterHandler implements SheetWriteHandler {private final…

c++ 類型轉換函數

測試代碼&#xff1a; void testTypeTransfer() { // 測試類型轉換函數class Distance {private:int meters;public:// 類型轉換函數&#xff0c;int表示轉化為int類型operator int() {std::cout << "調用了類型轉換函數" << endl;return meters; }Dist…

Conda 基本使用命令大全

Conda 基本使用命令大全 Conda 是一個開源的包管理和環境管理系統&#xff0c;廣泛用于 Python 開發、數據科學和機器學習。以下是 最常用的 Conda 命令&#xff0c;涵蓋環境管理、包安裝、配置等核心操作。 1. 環境管理 創建環境 conda create --name myenv # 創…

基于SpringBoot和PostGIS的OSM時空路網數據入庫實踐

目錄 前言 一、空間表的設計 1、屬性信息 2、空間表結構設計 二、路網數據入庫 1、實體類設計 2、路網數據寫入 3、pgAdmin數據查詢 三、總結 前言 在當今數字化時代&#xff0c;隨著信息技術的飛速發展&#xff0c;地理空間數據的應用范圍越來越廣泛&#xff0c;尤其是…

代付入賬是什么意思?怎么操作?

代付入賬就是指商戶委托銀行通過企業銀行賬戶向指定持卡人賬戶劃付款項&#xff0c;款項劃入指定賬戶即為入賬。 具體操作流程如下&#xff1a; 1. 向第三方支付公司指定賬戶充值加款。 2. 通過操作后臺提交代付銀行卡信息。 3. 第三方支付公司受理業務申請。 4. 第三方審…

數學復習筆記 27

前言 太難受了。因為一些事情。和朋友傾訴了一下&#xff0c;也沒啥用&#xff0c;幾年之后不知道自己再想到的時候&#xff0c;會怎么考慮呢。另外&#xff0c;筆記還是有框架一點比較好&#xff0c;這樣比較有邏輯感受。不然太亂了。這篇筆記是關于線代第五章&#xff0c;特…

第四十五天打卡

知識點回顧&#xff1a; tensorboard的發展歷史和原理 tensorboard的常見操作 tensorboard在cifar上的實戰&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很適合拿去組會匯報撐頁數&#xff1a; 作業&#xff1a;對resnet18在cifar10上采用微調策略下&#xff0c;用tensor…

使用高斯樸素貝葉斯算法對鳶尾花數據集進行分類

高斯樸素貝葉斯算法通常用于特征變量是連續變量&#xff0c;符合高素分布的情況。 使用高斯樸素貝葉斯算法對鳶尾花數據集進行分類 """ 使用高斯貝葉斯堆鳶尾花進行分類 """ #導入需要的庫 from sklearn.datasets import load_iris from skle…

【docker】Windows安裝docker

環境及工具&#xff08;點擊下載&#xff09; Docker Desktop Installer.exe &#xff08;windows 環境下運行docker的一款產品&#xff09; wsl_update_x64 &#xff08;Linux 內核包&#xff09; 前期準備 系統要求2&#xff1a; Windows 11&#xff1a;64 位系統&am…

量化Quantization初步之--帶量化(QAT)的XOR異或pyTorch版250501

量化(Quantization)這詞兒聽著玄&#xff0c;經常和量化交易Quantitative Trading (量化交易)混淆。 其實機器學習(深度學習)領域的量化Quantization是和節約內存、提高運算效率相關的概念&#xff08;因大模型的普及&#xff0c;這個量化問題尤為迫切&#xff09;。 揭秘機器…

【Redis】zset 類型

zset 一. zset 類型介紹二. zset 命令zaddzcard、zcountzrange、zrevrange、zrangebyscorezpopmax、zpopminzrank、zrevrank、zscorezrem、zremrangebyrank、zremrangebyscorezincrby阻塞版本命令&#xff1a;bzpopmax、bzpopmin集合間操作&#xff1a;zinterstore、zunionstor…