Go語言GC機制:高效并發回收解析

Go 語言的垃圾回收(Garbage Collection,簡稱 GC)是其自動內存管理的核心機制,旨在自動識別并回收不再被使用的內存,避免內存泄漏,減輕開發者的手動內存管理負擔。Go 的 GC 算法經歷了多次迭代優化,目前采用的是并發標記 - 清除(Concurrent Mark and Sweep)?算法,并結合了多種優化技術,以實現低延遲、高吞吐量的目標。

一、Go 垃圾回收的核心目標

Go 的 GC 設計圍繞以下核心目標展開:

  1. 低延遲:盡可能減少 GC 對程序運行的阻塞時間(Stop-The-World,簡稱 STW),避免影響用戶程序的響應速度。
  2. 高吞吐量:在保證低延遲的同時,高效地回收內存,減少 GC 本身的性能開銷。
  3. 簡單高效:算法實現簡潔,適配 Go 語言的并發模型(如 goroutine)和內存分配機制。

二、Go 垃圾回收的核心算法:并發標記 - 清除(Concurrent Mark and Sweep)

Go 的 GC 基于追蹤式垃圾回收(通過追蹤對象的引用關系判斷是否存活),核心流程分為標記(Mark)?和清除(Sweep)?兩個階段,且大部分工作在用戶程序運行的同時(并發)執行,僅在關鍵節點需要短暫 STW。

[初始標記] → [并發標記] → [重新標記] → [并發清除](STW)       (并發)       (STW)        (并發)
1. 標記階段(Mark Phase)

標記階段的目標是識別出所有存活的對象(被當前程序直接或間接引用的對象),具體流程如下:

  • 初始標記(Initial Mark,STW)

    • 這是標記階段的第一個步驟,需要短暫 STW(通常只有幾微秒到幾十微秒)。
    • GC 會暫停所有用戶 goroutine,從根對象(Root Set)開始標記直接引用的對象。根對象包括:
      • 全局變量(如包級變量);
      • 當前運行的 goroutine 的棧內存(局部變量、函數參數等);
      • 寄存器中的引用(暫存的變量指針)。
    • 初始標記完成后,立即恢復用戶程序運行。
  • 并發標記(Concurrent Mark)

    • 初始標記后,用戶程序繼續運行,GC 同時在后臺(由專門的 GC 協程)進行標記。
    • 后臺 GC 協程會從初始標記的對象出發,遞歸遍歷所有可達的對象(通過對象的引用指針),并標記為 “存活”。
    • 由于用戶程序在運行時可能修改對象的引用關系(如新增、刪除指針),Go 采用寫屏障(Write Barrier)?技術跟蹤這些修改,確保標記的準確性:
      • 寫屏障會在用戶程序修改指針時(如?a = &b)觸發,記錄指針的變化,防止并發標記時遺漏或誤判對象的存活狀態。
  • 重新標記(Remark,STW)

    • 并發標記結束后,需要再次短暫 STW,處理并發標記期間因用戶程序修改引用而產生的 “漏標” 對象(稱為 “浮動垃圾” 的一部分)。
    • 重新標記會利用寫屏障記錄的指針變化,快速修正標記結果,確保所有存活對象都被標記。
2. 清除階段(Sweep Phase)

清除階段的目標是回收未被標記的對象(即垃圾)所占用的內存,具體流程如下:

  • 并發清除(Concurrent Sweep)
    • 清除階段完全并發執行,不阻塞用戶程序。
    • GC 會遍歷堆內存,釋放所有未被標記的對象(垃圾),并將其內存塊歸還給空閑內存池,供后續內存分配使用。
    • 清除過程中,若用戶程序需要分配新內存,會優先復用已回收的空閑內存,減少內存碎片。

三、Go GC 的關鍵優化技術

為實現低延遲和高吞吐量,Go 引入了多項優化技術:

1. 寫屏障(Write Barrier)
  • 作用:在并發標記階段,跟蹤用戶程序對指針的修改,防止因引用關系變化導致的標記錯誤。
  • 實現:Go 使用Dijkstra 寫屏障(早期版本)和混合寫屏障(Go 1.8 及以后,結合了 Dijkstra 和 Yuasa 寫屏障的優勢),在指針賦值時插入額外邏輯,記錄舊指針和新指針的信息,確保并發標記的準確性。
  • Dijkstra 寫屏障:當修改指針時,將舊指針指向的對象標記為灰色(防止舊對象被漏標)
  • Yuasa 寫屏障:當修改指針時,將新指針指向的對象標記為灰色(防止新對象被漏標)
  • // 偽代碼:指針賦值時觸發的寫屏障
    func writeBarrier(old *T, new *T) {// 1. 將舊指針指向的對象標記為灰色(Dijkstra 邏輯)gray(old)// 2. 將新指針指向的對象標記為灰色(Yuasa 邏輯)gray(new)
    }

2. 三色標記法(Tri-Color Marking)
  • 標記階段通過 “三色” 區分對象的狀態,簡化并發標記的管理:
    • 白色:未被標記的對象(初始狀態,可能是垃圾);
    • 灰色:已被標記,但引用的子對象尚未遍歷(待處理);
    • 黑色:已被標記,且所有子對象都已遍歷(確定存活)。
  • 流程:初始標記將根對象設為灰色,并發標記時將灰色對象的子對象標記為灰色、自身設為黑色,最終所有黑色對象為存活,白色為垃圾。
3. 增量 GC 與并發執行
  • Go 的 GC 不是一次性完成所有工作,而是將標記和清除階段拆分為可中斷、可并發的步驟,大部分工作與用戶程序并行執行,僅在初始標記和重新標記階段短暫 STW,大幅降低了對程序運行的影響。
4. 內存分代(Generational GC)的部分實現
  • 雖然 Go 沒有嚴格的 “分代” 設計(如 Java 的新生代、老年代),但通過對象年齡判斷(如頻繁分配和回收的小對象更可能被優先處理)和內存塊大小分類(如 tiny、small、large 分配器),優化了 GC 對短期對象的回收效率。
5. 自適應觸發機制
  • GC 觸發時機并非固定,而是根據內存分配速率、堆內存大小等動態調整:
    • 當堆內存增長到上次 GC 后堆大小的 2 倍(可通過?GOGC?環境變量調整,默認 100)時觸發;
    • 若內存分配速率過快,也會提前觸發,避免內存溢出。

三、Go GC 的演進歷程

Go 的 GC 算法經過多次重大優化,核心版本演進如下:

  • Go 1.0:采用簡單的標記 - 清除算法,STW 時間長(毫秒級)。
  • Go 1.5:引入并發標記 - 清除,STW 時間縮短至百微秒級。
  • Go 1.8:使用混合寫屏障,進一步減少 STW 時間(通常低于 100 微秒)。
  • Go 1.12+:優化了重新標記階段的效率,引入更多并發優化,使 STW 時間可穩定在微秒級。

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

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

相關文章

imx6ull-驅動開發篇23——Linux 內核定時器實驗

目錄 實驗程序編寫 修改設備樹文件 定時器驅動程序 timer.c 測試 timerApp.c Makefile 文件 運行測試 實驗程序編寫 本講實驗,我們使用正點原子I.MX6U-ALPHA 開發板,通過linux內核定時器周期性的點亮和熄滅開發板上的 LED 燈, LED 燈…

IPTV系統:開啟視聽與管理的全新篇章

在當今數字化飛速發展的時代,IPTV系統正以前所未有的姿態,重塑著我們的視聽體驗與管理模式。它不僅僅是一套技術系統,更是連接信息、溝通情感、提升效率的橋梁,為各個領域帶來了全新的變革與發展機遇。從電視直播的角度來看&#…

PyTorch筆記9----------Cifar10圖像分類

1.圖像分類網絡模型框架解讀 分類網絡的基本結構 數據加載模塊:對訓練數據加載數據重組:組合成網絡需要的形式,例如預處理、增強、各種網絡處理、loss函數計算優化器 數據加載模塊 使用公開數據集:torchvision.datasets使用自定義…

飛凌OK3568開發板QT應用程序編譯流程

飛凌OK3568開發板QT應用程序編譯流程開發環境:ubuntu20.04(主機)、飛凌OK3568開發板一般在linux系統下開發用于ARM開發板的QT應用程序時,直接在主機上開發然后進行交叉編譯即可,但有時候ARM開發板的廠家提供的SDK中可能…

飛算JavaAI合并項目實戰:7天完成3年遺留系統重構

引言 企業數字化進程中,遺留系統改造始終是CIO面臨的頭號難題。某電商平臺的實踐數據顯示:3年以上的Java項目平均存在47%的冗余代碼,63%的架構設計不符合當前業務需求,進行系統性重構需要投入相當于原開發量200%的資源。傳統&quo…

衛星速度增量和比沖及推力之間的關系

一、定義1.1.比沖(Isp):比沖是衡量發動機性能的重要指標,反映了單位重量推進劑在發動機中產生的沖量,單位為米/秒(m/s),代表燃料燃燒時噴流速度。這個單位與速度單位“米/秒”相同&a…

MATLAB繪制各種心形曲線

1.方程(1)心形線的經典隱函數方程為:(2)參數方程(更平滑的心形):(3)極坐標心形線(4)參數方程(3D心形)(5)隱函數3D心形2. MATLAB代碼clc;close all;clear all;warning off;%清除變量 rand(seed, 100); randn…

Django REST Framework視圖

Django REST Framework (DRF) 視圖類詳解DRF 提供了豐富的視圖類來構建 API,從基礎到高級,滿足不同復雜度的需求。以下是 DRF 的主要視圖類及其使用場景:1. 基礎視圖類APIView所有 DRF 視圖的基類,相當于 Django 的 View 類的增強…

Linux面試題及詳細答案 120道(1-15)-- 基礎概念

《前后端面試題》專欄集合了前后端各個知識模塊的面試題,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

week1-[分支結構]中位數

week1-[分支結構]中位數 題目描述 給定 444 個正整數 a,b,c,da,b,c,da,b,c,d,輸出它們的中位數,答案四舍五入保留 111 位小數。 輸入格式 輸入共 111 行 444 個正整數 a,b,c,da,b,c,da,b,c,d。 輸出格式 輸出共 111 行 111 個浮點數表示答案。 樣例 #1 樣…

[激光原理與應用-259]:理論 - 幾何光學 - 平面鏡的反射、平面透鏡的折射、平面鏡的反射成像、平面透鏡的成像的規律

一、平面鏡的反射規律平面鏡的反射遵循鏡面反射定律,即光線在光滑表面(反射面平整度遠大于波長)發生反射時,滿足以下條件:反射光線、入射光線與法線共面:反射光線、入射光線和法線(垂直于反射面…

相機按鍵功能解析

相機按鍵功能解析佳能相機按鍵機身背面機身正面機身頂部機身側面 佳能相機按鍵 機身背面取景器目鏡:用于拍攝時觀察相機形成的圖像。實拍顯示/視頻拍攝按鈕:按下即可開始拍攝或錄制視頻。光圈/曝光補償鍵:調整光圈大小和曝光補償,…

51單片機-驅動LED模塊教程

本章思維導圖: 51單片機驅動LED燈模塊 LED燈元器件簡介 LED(Light Emitting Diode,發光二極管) 是一種固態半導體器件,通過P-N結中電子與空穴復合直接將電能轉化為光能。其核心結構由P型半導體(空穴主導&a…

Git 完全手冊:從入門到團隊協作實戰(2)

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《C修煉之路》、《Linux修煉&#xff1a;終端之內 洞悉真理…

c語言中堆和棧的區別

1.棧區(stack):由編譯器自動分配釋放&#xff0c;棧主要用于存儲局部變量、函數參數、函數調用和返回信息等。其操作方式類似于數據結構中的棧。 2.堆區(heap):一般由程序員分配釋放&#xff0c;若程序員不釋放&#xff0c;則可能會引起內存泄漏。注堆和數據結構中的堆棧不一樣…

華為實驗WLAN 基礎配置隨練

業務vlan 20 192.168.20.x管理vlan 100 192.168.100.x步驟① 網絡互通Core sw:vlan batch 20 100 dhcp enable int vlanif 20IP add 192.168.20.1 24dhcp select interfaceinterface GigabitEthernet0/0/1/2port link-type trunkport trunk pvid vlan 100port trunk allow-pas…

CMake 如何查找 Python2和Python3

問題 在一個CMakeLists.txt文件里面看到了下面的這句話 find_package(Python2 COMPONENTS Interpreter Development NumPy)這個好有趣啊&#xff0c;Python2也是一個C的庫嗎&#xff0c;也有Python2Config.cmake或者FindPython2.cmake? 回答 find_package(Python2 COMPONENTS …

心靈筆記:刻意練習

心靈筆記&#xff1a;刻意練習提要 所有人都以為“杰出”源于“天賦”&#xff0c;而“天才”卻說&#xff1a;我的成就源于“正確的練習”&#xff01; 定義&#xff1a;刻意練習是一種有目的、有方法、能帶來能力持續提升的結構化訓練方式&#xff0c;它并非簡單的重復勞動&a…

langchain入門筆記03:使用fastapi部署本地大模型后端接口,優化局域網內的問答響應速度

文章目錄前言一、fastapi的簡單入門1&#xff1a;安裝必要的包&#xff08;python3.11&#xff09;&#xff1a;2&#xff1a;快速搭建一個fastapi&#xff1a;二、提升問答的響應速度1. fastapi部署后端接口&#xff0c;在局域網內訪問的方法2. 局域網內的測試&#xff1a;“未…

【CDA 新一級】學習筆記第1篇:數據分析的時代背景

作者&#xff1a;CDA持證人 張九領我們要學習數據分析&#xff0c;就要從當前時代的數據特點&#xff0c;找到在時代特點下企業需要數據分析的痛點&#xff0c;然后理解數據分析在企業中的作用。當前時代&#xff0c;數據分析的特征是哪些呢&#xff1f;我們用VUCA來概括數據分…