<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>

          『每周譯Go』golang 垃圾回收器如何標(biāo)記內(nèi)存?

          共 2677字,需瀏覽 6分鐘

           ·

          2021-07-04 12:23



          本文基于 Go 1.13。這里討論的關(guān)于內(nèi)存管理的概念在我的文章Go:內(nèi)存管理和分配 中有解釋

          Go 垃圾回收器負(fù)責(zé)回收不再使用的內(nèi)存。實現(xiàn)的算法是一個并行的三色標(biāo)記掃描采集器。在本文中,我們將詳細(xì)了解標(biāo)記階段,以及不同顏色的用法。

          您可以在 kenfox 的可視化垃圾回收算法 中找到關(guān)于不同類型垃圾回收器的更多信息。

          標(biāo)記階段

          此階段執(zhí)行內(nèi)存掃描,以了解代碼仍在使用哪些塊,以及應(yīng)該回收哪些塊。

          但是,由于垃圾回收器可以與我們的 Go 程序同時運行,因此它需要一種在掃描時檢測內(nèi)存中潛在變化的方法。為了解決這個潛在的問題,實現(xiàn)了一個寫屏障算法,允許 Go 跟蹤任何指針的變化。啟用寫屏障的唯一條件是短時間停止程序,也稱為 “STW”:



          在進(jìn)程開始時,Go 還會為每個處理器啟動一個標(biāo)記輔助進(jìn)程,以幫助標(biāo)記內(nèi)存。

          然后,一旦根節(jié)點被排隊等待處理,標(biāo)記階段就可以開始遍歷內(nèi)存并為其著色。

          現(xiàn)在讓我們以一個簡單的程序為例,該程序允許我們遵循標(biāo)記階段所做的步驟

          Type struct1 struct {
              a, b int64
              c, d float64
              e *struct2
          }

          type struct2 struct {
              f, g int64
              h, i float64
          }

          func main() {
              s1 := allocStruct1()
              s2 := allocStruct2()

              func () {
                  _ = allocStruct2()
              }()

              runtime.GC()

              fmt.Printf("s1 = %X, s2 = %X\n", &s1, &s2)
          }

          //go:noinline
          func allocStruct1() *struct1 {
              return &struct1{
                  e: allocStruct2(),
              }
          }

          //go:noinline
          func allocStruct2() *struct2 {
              return &struct2{}
          }

          由于 struct subStruct 不包含任何指針,因此它存儲在一個專用于對象的范圍中,而不引用其他對象:


          這使得垃圾回收器的工作更容易,因為它在標(biāo)記內(nèi)存時不必掃描這個范圍。

          一旦分配完成,我們的程序就會強(qiáng)制垃圾回收器運行一個周期。以下是工作流程:


          垃圾回收器從堆棧開始標(biāo)記,然后跟著指針遞歸遍歷內(nèi)存。直到對象都被標(biāo)記時停止掃描。然而,這個過程不是在同一個 goroutine 中完成的 完成的;每個指針都在工作池中排隊。然后 ,后臺的標(biāo)記線程發(fā)現(xiàn)之前的出列隊列是來自該工作池,掃描對象,然后將在其中找到的指針加入隊列:


          著色!

          后臺線程現(xiàn)在需要一種方法來跟蹤哪些內(nèi)存有沒有被掃描。垃圾回收器使用三色算法,其工作原理如下:

          • 所有對象一開始都被認(rèn)為是白色的

          • 根對象(堆棧、堆、全局變量)將以灰色顯示

          完成此主要步驟后,垃圾回收器將:

          • 選擇一個灰色的對象,把它涂成黑色

          • 遵循此對象的所有指針并將所有引用的對象涂成灰色

          然后,它將重復(fù)這兩個步驟,直到?jīng)]有更多的對象要著色。從這一點來看,對象不是黑色就是白色。白色集合表示未被任何其他對象引用且準(zhǔn)備好回收的對象。

          下面是使用上一個示例對其進(jìn)行的表示:



          作為第一種狀態(tài),所有對象都被視為白色。然后,對象被遍歷,可到達(dá)的對象將變?yōu)榛疑H绻麑ο笪挥跇?biāo)記為 “無掃描” 的范圍內(nèi),則可以將其繪制為黑色,因為不需要對其進(jìn)行掃描:



          灰色對象現(xiàn)在入隊等待掃描并變黑:



          在沒有更多的對象要處理之前,入隊的對象也會發(fā)生同樣的情況:



          在進(jìn)程結(jié)束時,黑色對象是內(nèi)存中正在使用的對象,而白色對象是要回收的對象。如我們所見,由于 struct2 的實例是在匿名函數(shù)中創(chuàng)建的,并且無法從堆棧訪問,因此它保持為白色,可以清除。

          由于每個跨度中有一個名為 gcmarkBits 的位圖屬性,顏色在內(nèi)部實現(xiàn),該屬性跟蹤掃描,并將相應(yīng)的位設(shè)置為 1:



          正如我們所見,黑色和灰色的工作原理是一樣的。這一過程的不同之處在于,當(dāng)黑色對象結(jié)束掃描鏈時,灰色對象排隊等待掃描。

          垃圾回收器最終會 stops the world,將每個寫屏障上所做的更改刷新到工作池,并執(zhí)行剩余的標(biāo)記。

          您可以在我的文章Go:垃圾回收器如何監(jiān)視您的應(yīng)用程序 中找到有關(guān)并發(fā)進(jìn)程和垃圾回收器中標(biāo)記階段的更多詳細(xì)信息

          運行時分析器

          Go 提供的工具允許我們可視化所有這些步驟,并在程序中查看垃圾回收器的影響。在啟用跟蹤的情況下運行我們的代碼提供了前面步驟的一個大圖。以下是 traces:



          標(biāo)記線程的生命周期也可以在 goroutine 級別的 tracer 中可視化。下面是 goroutine#33 的示例,它在開始標(biāo)記內(nèi)存之前先在后臺等待。



          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  日本逼逼网 | 午夜精品视频 | 在线观看视频草女人啊啊 | 日本三级片东京热 | 人人透人人摸 |