大家一起學Golang——Go runtime內存分配

大家一起學Golang——Go runtime內存分配

go runtime內存分配

摒棄傳統內存分配方式,使用自主管理,不需要每次系統調用分配內存,TCMalloc算法進行內存分配。

基本策略:

  1. 每次從操作系統申請大的內存,減少系統的調用
  2. 將申請的大內存按照固定的大小進行劃分,並以鏈表的形式連起來
  3. 爲對象分配內存時,需要從合適大小的鏈表取一塊內存
  4. 回收對象時,將小塊內存重新加到鏈表中,以便回收利用,提高利用率
  5. 如果閒置的內存增多,會嘗試將部分內存歸還操作系統,降低整體開銷

內存管理單元:

  1. span 面向內存管理,由多個連續頁(page 8kb大小)組成的大塊內存
  2. object 面向對象分配,將span切成多個小塊,每小塊可以存儲對象
    在這裏插入圖片描述
  • arena區域
    就是所謂的堆區,很多個8kb的頁,一些頁組合稱爲mspan
  • bitmap區域
    標識arena哪些區域地址保存了對象,並用4bit地址保存對象是否包含指針和GC標記
  • spans區域
    用來存放mspan指針,對應到每一個頁page,spans區域大小512GB/8KB*8B=512MB

內存管理組件:

heap --> central --> cache

  • cache
    每個工作線程綁定1個mcahce,1個mcache管理n個mspan的空間
  • central
    central爲所有的mcache提供切分好的mspan的資源
    當mcache從mcentral中申請一個page爲8k大小,然後按照相同規格進行分割mspan,在object中進行使用。
  • heap
    管理閒置的span, mheap對象來進行管理堆內存,mcentral沒有空間的mspan時,向mheap申請,mheap沒有,則mheap向操作系統申請。mheap主要用於大對象的內存分配,管理未分割的mspan。mcentral來切割成小對象。

對於go運行時內存的分配的知識點,一般開發人員瞭解上述內容就差不多了。Go內存分配源碼涉及鏈表結構,要理解每個部分的層級關係。更詳細可參見 TCMallo解密 這個可是相當的詳細~~

內存分配總結:

Go在程序啓動時,會向操作系統申請⼀大塊內存,然後自⾏管理。 Go內存管理的基本單元是mspan,它由若⼲個page頁組成,每mspan可以分配特定⼤小的object。 mcache, mcentral, mheap是Go內存管理理的三⼤組件,層遞進。mcache管理線程在本地緩存的mspan;mcentral管理全局的mspan供所有線程使用;mheap管理Go的所有動態分配內存。 一般小對象通過mspan分配內存,⼤對象則直接由mheap分配內存。