golang內存管理基本是參考tcmalloc來進行的。go內存管理本質上是一個內存池,只不過內部做了很多優化:自動伸縮內存池大小,合理切割內存塊。
?
基本概念:
Page:頁,一塊 8 K大小的內存空間。Go向操作系統申請和釋放內存都是以頁為單位。
span:內存塊,一個或多個page組成一個span。如果把page比喻成工人,span可以看成是小隊,工人被分成若干個隊伍,不同的隊伍干不同的活。
sizeclass:空間規格,每個span都帶有一個sizeclass,標記著該span中的 page 應該如何使用。使用上面的比喻,就是sizeclass標志著 span 是一個什么樣的隊伍。
object:對象,用來存儲一個變量數據內存空間,一個span在初始化時,會被切割成一堆等大的object。假設object的大小是 16B,span大小是 8K,那么就會把 span 中的 page 共初始化為 8k/16B = 512 個 object。所謂內存分配就是分配一個object出去。
mheap
一開始 go從操作系統索取一大塊內存作為內存池,并放在一個叫mheap的內存池進行管理,mheap將一整塊內存切割為不同的區域,并將每一部分內存切割為合適的大小。
?mheaps.spans:用來存儲 page 和 span 信息,比如每一個 span 的起始地址是多少,有幾個 page ,已使用了多少page等等
mheap.bitmap:保存arena對應的某個地址是否存在對象,以及對象是否被gc掃描過,主要用于gc
mheap.arena_start:將要分配給應用程序使用的空間(由一個個page組成)。
mcentral
用途相同的 span 會以鏈表的形式組織在一起存放在 mcentral 中。這里用途用sizeclass來表示,就是該 span 存儲到哪種大小的對象。
找到合適的 span 后,會從中取出一個 object 返回給上層使用
?
mcache
為了提高內存并發申請效率,加入緩存層mcache。每一個mcache和處理器P對應。Go申請內存首先從P的mcache中分配,如果沒有可用的span再從mcentral中獲取。
?