日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

Go的三色標(biāo)記GC

  • 引用計(jì)數(shù):對(duì)每個(gè)對(duì)象維護(hù)一個(gè)引用計(jì)數(shù),當(dāng)引用該對(duì)象的對(duì)象被銷毀時(shí),引用計(jì)數(shù)減1,當(dāng)引用計(jì)數(shù)器為0是回收該對(duì)象。
  • 優(yōu)點(diǎn):對(duì)象可以很快的被回收,不會(huì)出現(xiàn)內(nèi)存耗盡或達(dá)到某個(gè)閥值時(shí)才回收。
  • 缺點(diǎn):不能很好的處理循環(huán)引用,而且實(shí)時(shí)維護(hù)引用計(jì)數(shù),有也一定的代價(jià)。
  • 代表語(yǔ)言:Python、php、Swift
  • 標(biāo)記-清除:從根變量開始遍歷所有引用的對(duì)象,引用的對(duì)象標(biāo)記為"被引用",沒(méi)有被標(biāo)記的進(jìn)行回收。
  • 優(yōu)點(diǎn):解決了引用計(jì)數(shù)的缺點(diǎn)。
  • 缺點(diǎn):需要STW,即要暫時(shí)停掉程序運(yùn)行。
  • 代表語(yǔ)言:Golang(其采用三色標(biāo)記法)
  • 分代收集:按照對(duì)象生命周期長(zhǎng)短劃分不同的代空間,生命周期長(zhǎng)的放入老年代,而短的放入新生代,不同代有不能的回收算法和回收頻率。
  • 優(yōu)點(diǎn):回收性能好
  • 缺點(diǎn):算法復(fù)雜
  • 代表語(yǔ)言: JAVA,python

root

首先標(biāo)記root根對(duì)象,根對(duì)象的子對(duì)象也是存活的。

根對(duì)象包括:全局變量,各個(gè)G stack上的變量等。

標(biāo)記

在之前的Go語(yǔ)言——內(nèi)存管理一文中,分析過(guò)span是內(nèi)存管理的最小單位,所以猜測(cè)gc的粒度也是span。

type mspan struct {

// allocBits and gcmarkBits hold pointers to a span's mark and

// allocation bits. The pointers are 8 byte aligned.

// There are three arenas where this data is held.

// free: Dirty arenas that are no longer accessed

// and can be reused.

// next: Holds information to be used in the next GC cycle.

// current: Information being used during this GC cycle.

// previous: Information being used during the last GC cycle.

// A new GC cycle starts with the call to finishsweep_m.

// finishsweep_m moves the previous arena to the free arena,

// the current arena to the previous arena, and

// the next arena to the current arena.

// The next arena is populated as the spans request

// memory to hold gcmarkBits for the next GC cycle as well

// as allocBits for newly allocated spans.

//

// The pointer arithmetic is done "by hand" instead of using

// arrays to avoid bounds checks along critical performance

// paths.

// The sweep will free the old allocBits and set allocBits to the

// gcmarkBits. The gcmarkBits are replaced with a fresh zeroed

// out memory.

allocBits *gcBits

gcmarkBits *gcBits

}

Go垃圾回收GC詳解

bitmap

如圖所示,通過(guò)gcmarkBits位圖標(biāo)記span的塊是否被引用。對(duì)應(yīng)內(nèi)存分配中的bitmap區(qū)。

三色標(biāo)記

  • 灰色:對(duì)象已被標(biāo)記,但這個(gè)對(duì)象包含的子對(duì)象未標(biāo)記
  • 黑色:對(duì)象已被標(biāo)記,且這個(gè)對(duì)象包含的子對(duì)象也已標(biāo)記,gcmarkBits對(duì)應(yīng)的位為1(該對(duì)象不會(huì)在本次GC中被清理)
  • 白色:對(duì)象未被標(biāo)記,gcmarkBits對(duì)應(yīng)的位為0(該對(duì)象將會(huì)在本次GC中被清理)

例如,當(dāng)前內(nèi)存中有A~F一共6個(gè)對(duì)象,根對(duì)象a,b本身為棧上分配的局部變量,根對(duì)象a、b分別引用了對(duì)象A、B, 而B對(duì)象又引用了對(duì)象D,則GC開始前各對(duì)象的狀態(tài)如下圖所示:

  1. 初始狀態(tài)下所有對(duì)象都是白色的。
  2. 接著開始掃描根對(duì)象a、b; 由于根對(duì)象引用了對(duì)象A、B,那么A、B變?yōu)榛疑珜?duì)象,接下來(lái)就開始分析灰色對(duì)象,分析A時(shí),A沒(méi)有引用其他對(duì)象很快就轉(zhuǎn)入黑色,B引用了D,則B轉(zhuǎn)入黑色的同時(shí)還需要將D轉(zhuǎn)為灰色,進(jìn)行接下來(lái)的分析。
  3. 灰色對(duì)象只有D,由于D沒(méi)有引用其他對(duì)象,所以D轉(zhuǎn)入黑色。標(biāo)記過(guò)程結(jié)束
  4. 最終,黑色的對(duì)象會(huì)被保留下來(lái),白色對(duì)象會(huì)被回收掉。
Go垃圾回收GC詳解

STW

stop the world是gc的最大性能問(wèn)題,對(duì)于gc而言,需要停止所有的內(nèi)存變化,即停止所有的goroutine,等待gc結(jié)束之后才恢復(fù)。

觸發(fā)

  • 閾值:默認(rèn)內(nèi)存擴(kuò)大一倍,啟動(dòng)gc
  • 定期:默認(rèn)2min觸發(fā)一次gc,src/runtime/proc.go:forcegcperiod
  • 手動(dòng):runtime.gc()

go gc

Go垃圾回收GC詳解

go gc

GO的GC是并行GC, 也就是GC的大部分處理和普通的go代碼是同時(shí)運(yùn)行的, 這讓GO的GC流程比較復(fù)雜.

  1. Stack scan:Collect pointers from globals and goroutine stacks。收集根對(duì)象(全局變量,和G stack),開啟寫屏障。全局變量、開啟寫屏障需要STW,G stack只需要停止該G就好,時(shí)間比較少。
  2. Mark: Mark objects and follow pointers。標(biāo)記所有根對(duì)象, 和根對(duì)象可以到達(dá)的所有對(duì)象不被回收。
  3. Mark Termination: Rescan globals/changed stack, finish mark。重新掃描全局變量,和上一輪改變的stack(寫屏障),完成標(biāo)記工作。這個(gè)過(guò)程需要STW。
  4. Sweep: 按標(biāo)記結(jié)果清掃span

目前整個(gè)GC流程會(huì)進(jìn)行兩次STW(Stop The World), 第一次是Stack scan階段, 第二次是Mark Termination階段.

  • 第一次STW會(huì)準(zhǔn)備根對(duì)象的掃描, 啟動(dòng)寫屏障(Write Barrier)和輔助GC(mutator assist).
  • 第二次STW會(huì)重新掃描部分根對(duì)象, 禁用寫屏障(Write Barrier)和輔助GC(mutator assist).

從1.8以后的golang將第一步的stop the world 也取消了,這又是一次優(yōu)化; 1.9開始, 寫屏障的實(shí)現(xiàn)使用了Hybrid Write Barrier, 大幅減少了第二次STW的時(shí)間.

寫屏障

因?yàn)間o支持并行GC, GC的掃描和go代碼可以同時(shí)運(yùn)行, 這樣帶來(lái)的問(wèn)題是GC掃描的過(guò)程中g(shù)o代碼有可能改變了對(duì)象的依賴樹。

例如開始掃描時(shí)發(fā)現(xiàn)根對(duì)象A和B, B擁有C的指針。

  1. GC先掃描A,A放入黑色
  2. B把C的指針交給A
  3. GC再掃描B,B放入黑色
  4. C在白色,會(huì)回收;但是A其實(shí)引用了C。

為了避免這個(gè)問(wèn)題, go在GC的標(biāo)記階段會(huì)啟用寫屏障(Write Barrier).

啟用了寫屏障(Write Barrier)后,在GC第三輪rescan階段,根據(jù)寫屏障標(biāo)記將C放入灰色,防止C丟失。

參考:

Go 垃圾回收原理

Golang源碼探索(三) GC的實(shí)現(xiàn)原理

分享到:
標(biāo)簽:語(yǔ)言
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定