最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

談?wù)揋o 什么時(shí)候會(huì)觸發(fā) GC問(wèn)題

 更新時(shí)間:2021年09月29日 15:43:55   作者:煎魚  
Go 語(yǔ)言作為一門新語(yǔ)言,在早期經(jīng)常遭到唾棄的就是在垃圾回收(下稱:GC)機(jī)制中 STW(Stop-The-World)的時(shí)間過(guò)長(zhǎng)。下面文章就對(duì)此話題展開,感興趣的小伙伴可以參考下面文章的內(nèi)容

在早期經(jīng)常遭到唾棄的就是在垃圾回收(下稱:GC)機(jī)制中 STW(Stop-The-World)的時(shí)間過(guò)長(zhǎng)。那么這個(gè)時(shí)候,我們又會(huì)好奇一點(diǎn),作為 STW 的起始,Go 語(yǔ)言中什么時(shí)候才會(huì)觸發(fā) GC 呢?

1、什么是 GC

在計(jì)算機(jī)科學(xué)中,垃圾回收(GC)是一種自動(dòng)管理內(nèi)存的機(jī)制,垃圾回收器會(huì)去嘗試回收程序不再使用的對(duì)象及其占用的內(nèi)存。

最早 John McCarthy 在 1959 年左右發(fā)明了垃圾回收,以簡(jiǎn)化 Lisp 中的手動(dòng)內(nèi)存管理的機(jī)制(來(lái)自 @wikipedia)。

2、為什么要 GC

手動(dòng)管理內(nèi)存挺麻煩,管錯(cuò)或者管漏內(nèi)存也很糟糕,將會(huì)直接導(dǎo)致程序不穩(wěn)定(持續(xù)泄露)甚至直接崩潰。

3、GC 觸發(fā)場(chǎng)景

GC 觸發(fā)的場(chǎng)景主要分為兩大類,分別是:

  • 系統(tǒng)觸發(fā):運(yùn)行時(shí)自行根據(jù)內(nèi)置的條件,檢查、發(fā)現(xiàn)到,則進(jìn)行 GC 處理,維護(hù)整個(gè)應(yīng)用程序的可用性。
  • 手動(dòng)觸發(fā):開發(fā)者在業(yè)務(wù)代碼中自行調(diào)用 runtime.GC 方法來(lái)觸發(fā) GC 行為。

3.1系統(tǒng)觸發(fā)

在系統(tǒng)觸發(fā)的場(chǎng)景中,Go 源碼的 src/runtime/mgc.go 文件,明確標(biāo)識(shí)了 GC 系統(tǒng)觸發(fā)的三種場(chǎng)景,分別如下:

const ( 
 gcTriggerHeap gcTriggerKind = iota 
 gcTriggerTime 
 gcTriggerCycle 
) 


  • gcTriggerHeap:當(dāng)所分配的堆大小達(dá)到閾值(由控制器計(jì)算的觸發(fā)堆的大小)時(shí),將會(huì)觸發(fā)。
  • gcTriggerTime:當(dāng)距離上一個(gè) GC 周期的時(shí)間超過(guò)一定時(shí)間時(shí),將會(huì)觸發(fā)。-時(shí)間周期以 runtime.forcegcperiod 變量為準(zhǔn),默認(rèn) 2 分鐘。
  • gcTriggerCycle:如果沒有開啟 GC,則啟動(dòng) GC。

在手動(dòng)觸發(fā)的 runtime.GC 方法中涉及。

3.2手動(dòng)觸發(fā)

在手動(dòng)觸發(fā)的場(chǎng)景下,Go 語(yǔ)言中僅有 runtime.GC 方法可以觸發(fā),也就沒什么額外的分類的。

但我們要思考的是,一般我們?cè)谑裁礃I(yè)務(wù)場(chǎng)景中,要涉及到手動(dòng)干涉 GC,強(qiáng)制觸發(fā)他呢?

需要手動(dòng)強(qiáng)制觸發(fā)的場(chǎng)景極其少見,可能會(huì)是在某些業(yè)務(wù)方法執(zhí)行完后,因其占用了過(guò)多的內(nèi)存,需要人為釋放。又或是 debug 程序所需。

3.3 基本流程

在了解到 Go 語(yǔ)言會(huì)觸發(fā) GC 的場(chǎng)景后,我們進(jìn)一步看看觸發(fā) GC 的流程代碼是怎么樣的,我們可以借助手動(dòng)觸發(fā)的 runtime.GC 方法來(lái)作為突破口。

核心代碼如下:

func GC() { 
 n := atomic.Load(&work.cycles) 
 gcWaitOnMark(n) 
 
 gcStart(gcTrigger{kind: gcTriggerCycle, n: n + 1}) 
   
 gcWaitOnMark(n + 1) 
 
 for atomic.Load(&work.cycles) == n+1 && sweepone() != ^uintptr(0) { 
  sweep.nbgsweep++ 
  Gosched() 
 } 
   
 for atomic.Load(&work.cycles) == n+1 && atomic.Load(&mheap_.sweepers) != 0 { 
  Gosched() 
 } 
   
 mp := acquirem() 
 cycle := atomic.Load(&work.cycles) 
 if cycle == n+1 || (gcphase == _GCmark && cycle == n+2) { 
  mProf_PostSweep() 
 } 
 releasem(mp) 
} 

在開始新的一輪 GC 周期前,需要調(diào)用 gcWaitOnMark 方法上一輪 GC 的標(biāo)記結(jié)束(含掃描終止、標(biāo)記、或標(biāo)記終止等)。

開始新的一輪 GC 周期,調(diào)用 gcStart 方法觸發(fā) GC 行為,開始掃描標(biāo)記階段。

需要調(diào)用 gcWaitOnMark 方法等待,直到當(dāng)前 GC 周期的掃描、標(biāo)記、標(biāo)記終止完成。

需要調(diào)用 sweepone 方法,掃描未掃除的堆跨度,并持續(xù)掃除,保證清理完成。在等待掃除完畢前的阻塞時(shí)間,會(huì)調(diào)用 Gosched 讓出。

在本輪 GC 已經(jīng)基本完成后,會(huì)調(diào)用 mProf_PostSweep 方法。以此記錄最后一次標(biāo)記終止時(shí)的堆配置文件快照。

結(jié)束,釋放 M。

3.4 在哪觸發(fā)

看完 GC 的基本流程后,我們有了一個(gè)基本的了解。但可能又有小伙伴有疑惑了?

本文的標(biāo)題是 “GC 什么時(shí)候會(huì)觸發(fā) GC”,雖然我們前面知道了觸發(fā)的時(shí)機(jī)。但是....Go 是哪里實(shí)現(xiàn)的觸發(fā)的機(jī)制,似乎在流程中完全沒有看到?

4、監(jiān)控線程

實(shí)質(zhì)上在 Go 運(yùn)行時(shí)(runtime)初始化時(shí),會(huì)啟動(dòng)一個(gè) goroutine,用于處理 GC 機(jī)制的相關(guān)事項(xiàng)。

代碼如下:

func init() { 
 go forcegchelper() 
} 
 
func forcegchelper() { 
 forcegc.g = getg() 
 lockInit(&forcegc.lock, lockRankForcegc) 
 for { 
  lock(&forcegc.lock) 
  if forcegc.idle != 0 { 
   throw("forcegc: phase error") 
  } 
  atomic.Store(&forcegc.idle, 1) 
  goparkunlock(&forcegc.lock, waitReasonForceGCIdle, traceEvGoBlock, 1) 
    // this goroutine is explicitly resumed by sysmon 
  if debug.gctrace > 0 { 
   println("GC forced") 
  } 
 
  gcStart(gcTrigger{kind: gcTriggerTime, now: nanotime()}) 
 } 
} 

在這段程序中,需要特別關(guān)注的是在 forcegchelper 方法中,會(huì)調(diào)用 goparkunlock 方法讓該 goroutine 陷入休眠等待狀態(tài),以減少不必要的資源開銷。

在休眠后,會(huì)由 sysmon 這一個(gè)系統(tǒng)監(jiān)控線程來(lái)進(jìn)行監(jiān)控、喚醒等行為:

func sysmon() { 
 ... 
 for { 
  ... 
  // check if we need to force a GC 
  if t := (gcTrigger{kind: gcTriggerTime, now: now}); t.test() && atomic.Load(&forcegc.idle) != 0 { 
   lock(&forcegc.lock) 
   forcegc.idle = 0 
   var list gList 
   list.push(forcegc.g) 
   injectglist(&list) 
   unlock(&forcegc.lock) 
  } 
  if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace)*1000000 <= now { 
   lasttrace = now 
   schedtrace(debug.scheddetail > 0) 
  } 
  unlock(&sched.sysmonlock) 
 } 
} 

這段代碼核心的行為就是不斷地在 for 循環(huán)中,對(duì) gcTriggerTime now 變量進(jìn)行比較,判斷是否達(dá)到一定的時(shí)間(默認(rèn)為 2 分鐘)。

若達(dá)到意味著滿足條件,會(huì)將 forcegc.g 放到全局隊(duì)列中接受新的一輪調(diào)度,再進(jìn)行對(duì)上面 forcegchelper 的喚醒。

5、堆內(nèi)存申請(qǐng)

在了解定時(shí)觸發(fā)的機(jī)制后,另外一個(gè)場(chǎng)景就是分配的堆空間的時(shí)候,那么我們要看的地方就非常明確了。

那就是運(yùn)行時(shí)申請(qǐng)堆內(nèi)存的 mallocgc 方法。核心代碼如下:

func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { 
 shouldhelpgc := false 
 ... 
 if size <= maxSmallSize { 
  if noscan && size < maxTinySize { 
   ... 
   // Allocate a new maxTinySize block. 
   span = c.alloc[tinySpanClass] 
   v := nextFreeFast(span) 
   if v == 0 { 
    v, span, shouldhelpgc = c.nextFree(tinySpanClass) 
   } 
   ... 
   spc := makeSpanClass(sizeclass, noscan) 
   span = c.alloc[spc] 
   v := nextFreeFast(span) 
   if v == 0 { 
    v, span, shouldhelpgc = c.nextFree(spc) 
   } 
   ... 
  } 
 } else { 
  shouldhelpgc = true 
  span = c.allocLarge(size, needzero, noscan) 
  ... 
 } 
 
 if shouldhelpgc { 
  if t := (gcTrigger{kind: gcTriggerHeap}); t.test() { 
   gcStart(t) 
  } 
 } 
 
 return x 
} 


小對(duì)象:如果申請(qǐng)小對(duì)象時(shí),發(fā)現(xiàn)當(dāng)前內(nèi)存空間不存在空閑跨度時(shí),將會(huì)需要調(diào)用 nextFree 方法獲取新的可用的對(duì)象,可能會(huì)觸發(fā) GC 行為。

大對(duì)象:如果申請(qǐng)大于 32k 以上的大對(duì)象時(shí),可能會(huì)觸發(fā) GC 行為。

總結(jié)
在這篇文章中,我們介紹了 Go 語(yǔ)言觸發(fā) GC 的兩大類場(chǎng)景,并分別基于大類中的細(xì)分場(chǎng)景進(jìn)行了一一說(shuō)明。

到此這篇關(guān)于談?wù)揋o 什么時(shí)候會(huì)觸發(fā) GC問(wèn)題的文章就介紹到這了,更多相關(guān)Go 什么時(shí)候會(huì)觸發(fā) GC??jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang實(shí)現(xiàn)Mongo數(shù)據(jù)庫(kù)增刪改查操作

    Golang實(shí)現(xiàn)Mongo數(shù)據(jù)庫(kù)增刪改查操作

    本文主要介紹了Golang實(shí)現(xiàn)Mongo數(shù)據(jù)庫(kù)增刪改查操作,我們使用了 MongoDB的官方Go驅(qū)動(dòng)程序,實(shí)現(xiàn)了插入、查詢、更新和刪除操作,感興趣的可以了解一下
    2024-01-01
  • Golang中make與new使用區(qū)別小結(jié)

    Golang中make與new使用區(qū)別小結(jié)

    Go語(yǔ)言中new和make是內(nèi)建的兩個(gè)函數(shù),主要用來(lái)創(chuàng)建分配類型內(nèi)存,本文主要給大家介紹了Go語(yǔ)言中函數(shù)new與make的使用和區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Golang捕獲panic堆棧信息的講解

    Golang捕獲panic堆棧信息的講解

    今天小編就為大家分享一篇關(guān)于Golang捕獲panic堆棧信息的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • Go基礎(chǔ)系列:Go切片(分片)slice詳解

    Go基礎(chǔ)系列:Go切片(分片)slice詳解

    這篇文章主要介紹了Go語(yǔ)言中的切片(分片)slice詳細(xì)說(shuō)明?,需要的朋友可以參考下
    2022-04-04
  • Goland使用delve進(jìn)行遠(yuǎn)程調(diào)試的詳細(xì)教程

    Goland使用delve進(jìn)行遠(yuǎn)程調(diào)試的詳細(xì)教程

    網(wǎng)上給出的使用delve進(jìn)行遠(yuǎn)程調(diào)試,都需要先在本地交叉編譯或者在遠(yuǎn)程主機(jī)上編譯出可運(yùn)行的程序,然后再用delve在遠(yuǎn)程啟動(dòng)程序,本教程會(huì)將上面的步驟簡(jiǎn)化為只需要兩步,1,在遠(yuǎn)程運(yùn)行程序2,在本地啟動(dòng)調(diào)試,需要的朋友可以參考下
    2024-08-08
  • golang常用加密解密算法總結(jié)(AES、DES、RSA、Sha1、MD5)

    golang常用加密解密算法總結(jié)(AES、DES、RSA、Sha1、MD5)

    在項(xiàng)目開發(fā)過(guò)程中,當(dāng)操作一些用戶的隱私信息,本文主要主要介紹了golang常用加密解密算法總結(jié)(AES、DES、RSA、Sha1MD5),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Golang使用crypto/ed25519實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證

    Golang使用crypto/ed25519實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證

    本文將深入探討如何在?Golang?中使用?crypto/ed25519?進(jìn)行數(shù)字簽名和驗(yàn)證,我們將從基本原理開始,逐步引導(dǎo)讀者了解生成密鑰對(duì)、進(jìn)行數(shù)字簽名,以及驗(yàn)證簽名的具體過(guò)程,希望對(duì)大家有所幫助
    2024-02-02
  • Golang搭建開發(fā)環(huán)境的圖文教程

    Golang搭建開發(fā)環(huán)境的圖文教程

    這篇文章主要介紹了Golang搭建開發(fā)環(huán)境,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • go code review 代碼調(diào)試

    go code review 代碼調(diào)試

    這篇文章主要為大家介紹了go code review 代碼調(diào)試方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Go測(cè)試之.golden文件使用示例詳解

    Go測(cè)試之.golden文件使用示例詳解

    這篇文章主要為大家介紹了Go測(cè)試之.golden文件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08

最新評(píng)論

台北县| 开阳县| 获嘉县| 吐鲁番市| 兴安盟| 新源县| 汝阳县| 涡阳县| 高阳县| 葫芦岛市| 通化县| 盖州市| 汝南县| 梅州市| 曲水县| 维西| 岐山县| 于田县| 莫力| 察哈| 汕头市| 华宁县| 云安县| 西华县| 江西省| 庆元县| 巨鹿县| 庄浪县| 渝中区| 河池市| 芦溪县| 巍山| 成武县| 潞城市| 上犹县| 祁东县| 丰城市| 枣阳市| 大英县| 准格尔旗| 青冈县|