<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          圖解Golang垃圾回收機(jī)制!

          共 3087字,需瀏覽 7分鐘

           ·

          2021-08-31 21:14

          上篇說到超超從匯編的角度的解析了make和new的區(qū)別,下面來到了面試中常見的考點(diǎn)GC,Go的GC常常因?yàn)樾阅軉栴}被業(yè)界所詬病,下面跟著超超來看看內(nèi)存垃圾是如何產(chǎn)生的,以及Go從1.3到1.8在GC上做了哪些改進(jìn)吧!

          內(nèi)存垃圾



          面試官:你知道程序的垃圾是怎么產(chǎn)生的嗎?

          考點(diǎn):Go內(nèi)存管理

          超超:程序在內(nèi)存上被分為堆區(qū)、棧區(qū)、全局?jǐn)?shù)據(jù)區(qū)、代碼段、數(shù)據(jù)區(qū)五個(gè)部分。對(duì)于C++等早期編程語言棧上的內(nèi)存由編譯器管理回收,堆上的內(nèi)存空間需要編程人員負(fù)責(zé)申請(qǐng)與釋放。在Go中棧上內(nèi)存仍由編譯器負(fù)責(zé)管理回收,而堆上的內(nèi)存由編譯器和垃圾收集器負(fù)責(zé)管理回收,給編程人員帶來了極大的便利性。

          垃圾是指程序向堆棧申請(qǐng)的內(nèi)存空間,隨著程序的運(yùn)行已經(jīng)不再使用這些內(nèi)存空間,這時(shí)如果不釋放他們就會(huì)造成垃圾也就是內(nèi)存泄漏。

          例如下面這段程序

           1package main
          2
          3//假設(shè)每個(gè)人都擁有自己都一部手機(jī)
          4type Person struct {
          5    phone *Phone
          6}
          7
          8type Phone struct {
          9    money int
          10}
          11
          12func main() {
          13    //定義一個(gè)Person為超超
          14    chao := new(Person)
          15
          16    //超超一開始用的是iphone12
          17    iphone := &Phone{money: 6599}
          18    chao.phone = iphone
          19
          20    //華為推出了鴻蒙,于是超超果斷入了一部mate40
          21    huawei := &Phone{money: 5899}
          22    chao.phone = huawei
          23
          24}

          隨著超超將手機(jī)從iPhone換成了華為,phone所指向的內(nèi)存空間就變成了垃圾,這時(shí)就需要對(duì)phone指向的內(nèi)存空間進(jìn)行回收,否則就變成了內(nèi)存泄漏。


          Go的垃圾回收機(jī)制



          面試官:那你來給我說說Go語言是如何實(shí)現(xiàn)GC的吧!

          考點(diǎn):GC的實(shí)現(xiàn)

          超超:那我從Go1.3開始說起吧,

          Go1.3使用的是標(biāo)記清除法,分下面四步進(jìn)行

          1. 進(jìn)行STW(stop the worl即暫停程序業(yè)務(wù)邏輯),然后從main函數(shù)開始找到不可達(dá)的內(nèi)存占用和可達(dá)的內(nèi)存占用

          2. 開始標(biāo)記,程序找出可達(dá)內(nèi)存占用并做標(biāo)記

          3. 標(biāo)記結(jié)束清除未標(biāo)記的內(nèi)存占用

          4. 結(jié)束STW停止暫停,讓程序繼續(xù)運(yùn)行,循環(huán)該過程直到main生命周期結(jié)束


          一開始的做法是將垃圾清理結(jié)束時(shí)才停止STW,后來優(yōu)化了方案將清理垃圾放到了STW之后,與程序運(yùn)行同時(shí)進(jìn)行,這樣做減小了STW的時(shí)長。但是STW會(huì)暫停用戶邏輯對(duì)程序的性能影響是非常大的,這種粒度的STW對(duì)于性能較高的程序還是無法接受,因此Go1.5采用了三色標(biāo)記法優(yōu)化了STW。

          Go1.5三色標(biāo)記法

          三色標(biāo)記算法將程序中的對(duì)象分成白色、黑色和灰色三類。白色對(duì)象表示暫無對(duì)象引用的潛在垃圾,其內(nèi)存可能會(huì)被垃圾收集器回收;灰色對(duì)象表示活躍的對(duì)象,黑色到白色的中間狀態(tài),因?yàn)榇嬖谥赶虬咨珜?duì)象的外部指針,垃圾收集器會(huì)掃描這些對(duì)象的子對(duì)象;黑色對(duì)象表示活躍的對(duì)象,包括不存在引用外部指針的對(duì)象以及從根對(duì)象可達(dá)的對(duì)象。


          三色標(biāo)記法分五步進(jìn)行

          1. 將所有對(duì)象標(biāo)記為白色

          2. 從根節(jié)點(diǎn)集合出發(fā),將第一次遍歷到的節(jié)點(diǎn)標(biāo)記為灰色放入集合列表中

          3. 遍歷灰色集合,將灰色節(jié)點(diǎn)遍歷到的白色節(jié)點(diǎn)標(biāo)記為灰色,并把灰色節(jié)點(diǎn)標(biāo)記為黑色

          4. 循環(huán)這個(gè)過程

          5. 直到灰色節(jié)點(diǎn)集合為空,回收所有的白色節(jié)點(diǎn)

          這種方法看似很好,但是將GC和程序會(huì)放一起執(zhí)行,會(huì)因?yàn)閏pu的調(diào)度出現(xiàn)下面這種情況,導(dǎo)致被引用的對(duì)象3會(huì)被垃圾回收掉,從而出現(xiàn)錯(cuò)誤。

          分析bug的根源所在,主要是因?yàn)槌绦蛟谶\(yùn)行過程中出現(xiàn)了下面?zhèn)z種情況

          1. 一個(gè)白色對(duì)象被黑色對(duì)象引用

          2. 灰色對(duì)象與它之間的可達(dá)關(guān)系的白色對(duì)象遭到破壞

          因此在此基礎(chǔ)上拓展出了倆種方法,強(qiáng)三色不變式和弱三色不變式

          1. 強(qiáng)三色不變式:不允許黑色對(duì)象引用白色對(duì)象

          2. 弱三色不變式:黑色對(duì)象可以引用白色,白色對(duì)象存在其他灰色對(duì)象對(duì)他的引用,或者他的鏈路上存在灰色對(duì)象

          為了實(shí)現(xiàn)這倆種不變式的設(shè)計(jì)思想,從而引出了屏障機(jī)制,即在程序的執(zhí)行過程中加一個(gè)判斷機(jī)制,滿足判斷機(jī)制則執(zhí)行回調(diào)函數(shù)。

          屏障機(jī)制分為插入屏障和刪除屏障,插入屏障實(shí)現(xiàn)的是強(qiáng)三色不變式,刪除屏障則實(shí)現(xiàn)了弱三色不變式。值得注意的是為了保證棧的運(yùn)行效率,屏障只對(duì)堆上的內(nèi)存對(duì)象啟用,棧上的內(nèi)存會(huì)在GC結(jié)束后啟用STW重新掃描。

          插入屏障:對(duì)象被引用時(shí)觸發(fā)的機(jī)制,當(dāng)白色對(duì)象被黑色對(duì)象引用時(shí),白色對(duì)象被標(biāo)記為灰色(棧上對(duì)象無插入屏障)。

          缺點(diǎn)在于:如果對(duì)象1在棧上新創(chuàng)建了一個(gè)對(duì)象6,由于棧沒有屏障機(jī)制,所以對(duì)象6仍為白色節(jié)點(diǎn)會(huì)被回收

          所以棧在GC迭代結(jié)束時(shí)(沒有灰色節(jié)點(diǎn)),會(huì)對(duì)棧執(zhí)行STW,重新進(jìn)行掃描清除白色節(jié)點(diǎn)。(STW時(shí)間為10-100ms)

          刪除屏障:對(duì)象被刪除時(shí)觸發(fā)的機(jī)制。如果灰色對(duì)象引用的白色對(duì)象被刪除時(shí),那么白色對(duì)象會(huì)被標(biāo)記為灰色。

          缺點(diǎn):這種做法回收精度較低,一個(gè)對(duì)象即使被刪除仍可以活過這一輪再下一輪被回收。(如果對(duì)象4沒有引用對(duì)象3,此時(shí)對(duì)象3應(yīng)該作為垃圾被回收,但是對(duì)象3卻要等到下一輪GC才會(huì)被回收)

          同樣也存在對(duì)棧的二次掃描影響程序的效率。

          Go1.8 三色標(biāo)記+混合寫屏障

          基于插入寫屏障和刪除寫屏障在結(jié)束時(shí)需要STW來重新掃描棧,所帶來的性能瓶頸,Go在1.8引入了混合寫屏障的方式實(shí)現(xiàn)了弱三色不變式的設(shè)計(jì)方式,混合寫屏障分下面四步

          1. GC開始時(shí)將棧上可達(dá)對(duì)象全部標(biāo)記為黑色(不需要二次掃描,無需STW)

          2. GC期間,任何棧上創(chuàng)建的新對(duì)象均為黑色

          3. 被刪除引用的對(duì)象標(biāo)記為灰色

          4. 被添加引用的對(duì)象標(biāo)記為灰色

          下面為混合寫屏障過程


          面試官:這個(gè)GC什么時(shí)候會(huì)被觸發(fā)呢?

          考點(diǎn):GC細(xì)節(jié)

          超超:觸發(fā)GC有倆個(gè)條件,一是堆內(nèi)存的分配達(dá)到控制器計(jì)算的觸發(fā)堆大小,初始大小環(huán)境變量GOGC,之后堆內(nèi)存達(dá)到上一次垃圾收集的 2 倍時(shí)才會(huì)觸發(fā)GC。二是如果一定時(shí)間內(nèi)沒有觸發(fā),就會(huì)觸發(fā)新的循環(huán),該觸發(fā)條件由runtime.forcegcperiod變量控制,默認(rèn)為 2 分鐘。


          面試官:說到這那我們?cè)倭囊幌耇CMalloc算法吧。

          超超:好的(自動(dòng)GC用的舒服,面試好難呀??????

          未完待續(xù)~




          如果你有什么問題想問超超,歡迎添加我的微信,進(jìn)讀者群和超超一起討論呀







          瀏覽 68
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久草青青 | 国产成人综合久久久久久 | 玖玖视频在线资源一区二区三区四区 | 国产性无码 | 亚洲日本看视频 |