golang垃圾回收參數,golang 垃圾回收

本文目錄一覽:

Golang的垃圾回收

最近垃圾分類的話題熱度一下子就上去了,很多人因為垃圾分類的問題很頭痛。因為垃圾這個話題,那我就想來說說Golang裡面的垃圾,於是就有了這篇博客,golang中的垃圾回收。

現階段網上針對golang垃圾回收的解析已經很多了,所以我也沒有必要仔仔細細的一點點說,還是那個原則,用最直白的話告訴你,垃圾到底是怎麼收的。

首先本文後續都會使用 GC 代替垃圾回收這幾個字。

我們知道創建對象會給他分配內存資源,如果這個對象不使用了,而這個內存資源卻一直被佔用的話,那麼我們的電腦很快就會被放滿,所以需要將這些垃圾對象進行回收。

要回收,那麼我們必須知道什麼才是垃圾,什麼不是垃圾。

在我們看來,一個對象以後都不用了,就是垃圾。

在程序看來,一個對象沒有被引用了,就是垃圾。

首先說明一下,下面說的停,都是STW,stop the world,全世界暫停,所有運行的都停下來了。

先告訴所有人,停一下,我來記錄一下當前狀態。

告訴所有人,你們繼續,該幹嘛幹嘛,我標記一下要用的對象

一開始所有點是白色,首先從根節點出發,標記相連的點為灰色(相連證明有引用),並且將所有灰色的點存起來;

告訴所有人,再停一下,在第二個過程中,因為所有人繼續在工作,那麼就會產生新的垃圾,因為第一個過程記錄了狀態,所以需要標記一下新的垃圾;然後清除所有白色的點,因為白色的點是沒人引用的,也就是垃圾。

你一定會有這樣的疑問:

那麼既然會導致那麼多問題,為什麼不直接停下來,標記完回收完了再開始呢?

因為慢~

所以這樣GC的原因是既要保證GC正常執行,又要保證效率,不能停的時間太長。

其實第一次停的時候,啟動了一個寫屏障 (write barrier)它需要記錄後續過程中新創建的對象

這個過程稱為三色標記,有點類似廣度優先搜索。

這次是必須停,因為在第二個過程中引用會發生變化,從而需要停止後重新掃描一遍;然後關閉寫屏障,最後再清理。

開啟寫屏障時需要stw

關閉寫屏障前需要stw

開啟寫屏障之後的標記過程與其他程序並發執行

關閉寫屏障之後的清掃過程與其他程序並發執行

那畢竟GC還是需要STW的,雖然可能停止時間很短,但是對於程序來說,整個程序停止1秒那對於用戶來說就是致命打擊。所以GC肯定需要一個觸發的條件,不能想來就來。

這是一個觸發的條件,默認GC百分比設置的是100,意思是,如果這次回收之後總共佔用2M的內存,那麼下次觸發的條件時當超過4M的時候;同理,當這次回收之後總共佔用4M,那麼下次觸發條件就是8M。

這個簡單,當一定時間(2分鐘)沒有執行過GC就觸發GC

使用命令 runtime.GC() 手動觸發GC

以上就是在golang中垃圾回收的大致流程,總的來說使用三色標記法進行標記清除,並且標記時與程序運行並行,為了解決問題使用寫屏障來記錄標記過程中對象的變更。總來的來說也是為了提高垃圾回收的效率,並且儘可能的減少STW的時間。

了解下來,與java的分代回收相比,golang中的回收演算法理解起來更加簡單一些。

【golang】內存逃逸常見情況和避免方式

因為如果變數的內存發生逃逸,它的生命周期就是不可知的,其會被分配到堆上,而堆上分配內存不能像棧一樣會自動釋放,為了解放程序員雙手,專註於業務的實現,go實現了gc垃圾回收機制,但gc會影響程序運行性能,所以要盡量減少程序的gc操作。

1、在方法內把局部變數指針返回,被外部引用,其生命周期大於棧,則溢出。

2、發送指針或帶有指針的值到channel,因為編譯時候無法知道那個goroutine會在channel接受數據,編譯器無法知道什麼時候釋放。

3、在一個切片上存儲指針或帶指針的值。比如[]*string,導致切片內容逃逸,其引用值一直在堆上。

4、因為切片的append導致超出容量,切片重新分配地址,切片背後的存儲基於運行時的數據進行擴充,就會在堆上分配。

5、在interface類型上調用方法,在Interface調用方法是動態調度的,只有在運行時才知道。

1、go語言的介面類型方法調用是動態,因此不能在編譯階段確定,所有類型結構轉換成介面的過程會涉及到內存逃逸發生,在頻次訪問較高的函數盡量調用介面。

2、不要盲目使用變數指針作為參數,雖然減少了複製,但變數逃逸的開銷更大。

3、預先設定好slice長度,避免頻繁超出容量,重新分配。

golang列印棧大小

8.1。根據查詢golang列印棧官方公布的參數顯示,golang列印棧大小為8.1,Go又稱Golang,是Google開發的一種靜態強類型、編譯型、並髮型,並具有垃圾回收功能的編程語言。

Golang什麼時候會觸發GC

Golang採用了三色標記法來進行垃圾回收,那麼在什麼場景下會觸發這個回收動作呢?

源碼主要位於文件 src/runtime/mgc.go go version 1.16

觸發條件從大方面說,可分為 手動觸發 和 系統觸發 兩種方式。手動觸發一般很少用,主要由開發者通過調用 runtime.GC() 函數來實現,而對於系統自動觸發是 運行時 根據一些條件判斷來進行的,這也正是本文要介紹的內容。

不管哪種觸發方式,底層回收機制是一樣的,所以我們先看一下手動觸發,根據它來找系統觸發的條件。

可以看到開始執行GC的是 gcStart() 函數,它有一個 gcTrigger 參數,是一個觸發條件結構體,它的結構體也很簡單。

其實在Golang 內部所有的GC都是通過 gcStart() 函數,然後指定一個 gcTrigger 的參數來開始的,而手動觸髮指定的條件值為 gcTriggerCycle 。 gcStart 是一個很複雜的函數,有興趣的可以看一下源碼實現。

對於 kind 的值有三種,分別為 gcTriggerHeap 、 gcTriggerTime 和 gcTriggerCycle 。

運行時會通過 gcTrigger.test() 函數來決定是否需要觸發GC,只要滿足上面基中一個即可。

到此我們基本明白了這三種觸發GC的條件,那麼對於系統自動觸發這種,Golang 從一個程序的開始到運行,它又是如何一步一步監控到這個條件的呢?

其實 runtime 在程序啟動時,會在一個初始化函數 init() 里啟用一個 forcegchelper() 函數,這個函數位於 proc.go 文件。

為了減少系統資源佔用,在 forcegchelper 函數里會通過 goparkunlock() 函數主動讓自己陷入休眠,以後由 sysmon() 監控線程根據條件來恢復這個gc goroutine。

可以看到 sysmon() 會在一個 for 語句里一直判斷這個 gcTriggerTime 這個條件是否滿足,如果滿足的話,會將 forcegc.g 這個 goroutine 添加到全局隊列里進行調度(這裡 forcegc 是一個全局變數)。

調度器在調度循環 runtime.schedule 中還可以通過垃圾收集控制器的 runtime.gcControllerState.findRunnabledGCWorker 獲取並執行用於後台標記的任務。

Golang 真的好用嗎?

好用,優點如下:

並發簡單、效率高

函數可以返回多個參數

垃圾回收(相比c/c++。不過java、c#都有這個優勢)

簡單易上手,語言特性少(也算缺點)

配套工具完善(pprof太好用了)

簡介

Go(又稱Golang)是Google開發的一種靜態強類型、編譯型、並髮型,並具有垃圾回收功能的編程語言。

羅伯特·格瑞史莫(Robert Griesemer),羅勃·派克(Rob Pike)及肯·湯普遜(Ken Thompson)於2007年9月開始設計Go,稍後Ian Lance Taylor、Russ Cox加入項目。Go是基於Inferno操作系統所開發的。Go於2009年11月正式宣布推出,成為開放源代碼項目。

並在Linux及Mac OS X平台上進行了實現,後來追加了Windows系統下的實現。在2016年,Go被軟體評價公司TIOBE 選為「TIOBE 2016 年最佳語言」。 目前,Go每半年發布一個二級版本(即從a.x升級到a.y)。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/254931.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-15 12:14
下一篇 2024-12-15 12:14

相關推薦

  • 三星內存條參數用法介紹

    本文將詳細解釋三星內存條上面的各種參數,讓你更好地了解內存條並選擇適合自己的一款。 一、容量大小 容量大小是內存條最基本的參數,一般以GB為單位表示,常見的有2GB、4GB、8GB…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變數時顯示的指定變數類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python input參數變數用法介紹

    本文將從多個方面對Python input括弧里參數變數進行闡述與詳解,並提供相應的代碼示例。 一、基本介紹 Python input()函數用於獲取用戶輸入。當程序運行到inpu…

    編程 2025-04-29
  • Spring Boot中發GET請求參數的處理

    本文將詳細介紹如何在Spring Boot中處理GET請求參數,並給出完整的代碼示例。 一、Spring Boot的GET請求參數基礎 在Spring Boot中,處理GET請求參…

    編程 2025-04-29
  • 使用Golang調用Python

    在現代軟體開發中,多種編程語言的協作是相當普遍的。其中一種使用場景是Golang調用Python,這使得在使用Python庫的同時,可以利用Golang的高性能和強大並發能力。這篇…

    編程 2025-04-29
  • Python Class括弧中的參數用法介紹

    本文將對Python中類的括弧中的參數進行詳細解析,以幫助初學者熟悉和掌握類的創建以及參數設置。 一、Class的基本定義 在Python中,通過使用關鍵字class來定義類。類包…

    編程 2025-04-29
  • Hibernate日誌列印sql參數

    本文將從多個方面介紹如何在Hibernate中列印SQL參數。Hibernate作為一種ORM框架,可以通過列印SQL參數方便開發者調試和優化Hibernate應用。 一、通過配置…

    編程 2025-04-29
  • Python函數名稱相同參數不同:多態

    Python是一門面向對象的編程語言,它強烈支持多態性 一、什麼是多態多態是面向對象三大特性中的一種,它指的是:相同的函數名稱可以有不同的實現方式。也就是說,不同的對象調用同名方法…

    編程 2025-04-29
  • 全能編程開發工程師必知——DTD、XML、XSD以及DTD參數實體

    本文將從大體介紹DTD、XML以及XSD三大知識點,同時深入探究DTD參數實體的作用及實際應用場景。 一、DTD介紹 DTD是文檔類型定義(Document Type Defini…

    編程 2025-04-29
  • Python可變參數

    本文旨在對Python中可變參數進行詳細的探究和講解,包括可變參數的概念、實現方式、使用場景等多個方面,希望能夠對Python開發者有所幫助。 一、可變參數的概念 可變參數是指函數…

    編程 2025-04-29

發表回復

登錄後才能評論