圖解 Go 內(nèi)存管理與內(nèi)存清理

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.
這篇文章基于 Go 1.13 版本。有關(guān)內(nèi)存管理的討論在我的文章 ?”Go:內(nèi)存管理與分配[1] ” 中有解釋。
清理內(nèi)存是一個(gè)過程,它能夠讓 Go 知道哪些內(nèi)存段最近可用于分配。但是,它并不會(huì)使用將位置 0 的方式來清理內(nèi)存。
將內(nèi)存置 0
將內(nèi)存置 0 的過程 —— 就是把內(nèi)存段中的所有位賦值為 0 —— 是在分配過程中即時(shí)執(zhí)行的。

Zeroing the memory
但是,我們可能想知道 Go 采用什么樣的策略去知道哪些對(duì)象能夠用于分配。由于在每個(gè)范圍內(nèi)有一個(gè)內(nèi)部位圖 allocBits ,Go 實(shí)際上會(huì)追蹤那些空閑的對(duì)象。讓我們從初始態(tài)開始來回顧一下它的工作流程,

Free objects tracking with allocBits
就性能角度來看,allocBits 代表了一個(gè)初始態(tài)并且會(huì)保持不變,但是它會(huì)由 freeIndex(一個(gè)指向第一個(gè)空閑位置的增量計(jì)數(shù)器)所協(xié)助。
然后,第一個(gè)分配就開始了:

Free objects tracking with allocBits
分配過程將會(huì)再一次出現(xiàn),之后, GC 將會(huì)啟動(dòng)去釋放不再被使用的內(nèi)存。在標(biāo)記期間,GC 會(huì)用一個(gè)位圖 gcmarkBits 來跟蹤在使用中的內(nèi)存。讓我們通過我們運(yùn)行的程序以相同的示例為例,在第一個(gè)塊不再被使用的地方。

Memory tracking during the garbage collector

Sweeping a span
清理階段
Go 提供了兩種方式來清理內(nèi)存:
使用一個(gè)工作程序在后臺(tái)等待,一個(gè)一個(gè)的清理這些范圍。 當(dāng)分配需要一個(gè)范圍的時(shí)候即時(shí)執(zhí)行。
關(guān)于后臺(tái)工作程序,當(dāng)開始運(yùn)行程序時(shí),Go 將設(shè)置一個(gè)后臺(tái)運(yùn)行的 Worker(唯一的任務(wù)就是去清理內(nèi)存),它將進(jìn)入睡眠狀態(tài)并等待內(nèi)存段掃描:

Background sweeper

Background sweeper

Spans are released to the central list

Sweep span on the fly during allocation
與 GC 周期的沖突
正如之前看到的,由于后臺(tái)只有一個(gè) worker 在清理內(nèi)存塊,清理過程可能會(huì)花費(fèi)一些時(shí)間。但是,我們可能想知道如果另一個(gè) GC 周期在一次清理過程中啟動(dòng)會(huì)發(fā)生什么。在這種情況下,這個(gè)運(yùn)行 GC 的 Goroutine 就會(huì)在開始標(biāo)記階段前去協(xié)助完成剩余的清理工作。讓我們舉個(gè)例子看一下連續(xù)調(diào)用兩次 GC,包含數(shù)千個(gè)對(duì)象的內(nèi)存分配的過程。

Sweeping must be finished before a new cycle
via:https://medium.com/a-journey-with-go/go-memory-management-and-memory-sweep-cc71b484de05作者:Vincent Blanchon[2]譯者:
[3]校對(duì):polaris1119[4]
本文由 GCTT[5] 原創(chuàng)編譯,Go 中文網(wǎng)[6] 榮譽(yù)推出
參考資料
Go:內(nèi)存管理與分配: https://medium.com/a-journey-with-go/go-memory-management-and-allocation-a7396d430f44
[2]Vincent Blanchon: https://medium.com/@blanchon.vincent
[3]sh1luo: https://github.com/sh1luo
[4]polaris1119: https://github.com/polaris1119
[5]GCTT: https://github.com/studygolang/GCTT
[6]Go 中文網(wǎng): https://studygolang.com/
推薦閱讀
站長(zhǎng) polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)
Go語言中文網(wǎng)
每天為你
分享 Go 知識(shí)
Go愛好者值得關(guān)注
