Go記憶體分配機制 TCMalloc

2021-10-19 22:44:01 字數 1981 閱讀 5134

本文是《循序漸進go語言》第四篇-go記憶體分配機制。

golang的記憶體採用了tcmalloc 這種分配機制。go是在多種語言誕生n多年之後,才由幾個大神開發的。每種語言都有自己的記憶體分配機制,那麼作為後起之秀,go為什麼選用tcmalloc呢?因為tcmalloc(thread-cache malloc) 在記憶體分配上效能做的更好,而且對記憶體的利用率也有所提高。先簡單說一下tcmalloc在這兩方面是如何做到的?

1.1 記憶體塊

go中的有兩種記憶體塊:span和object。span面向內部管理(可以是一種按照大小將記憶體頁進行組織的形式),object面向記憶體分配。

object: 將span按照特定大小切分成多個小塊,每個小塊可儲存乙個物件。

分配物件時,大的物件直接從堆上分配,小的物件從 span 中分配。

小物件分配.png

span跟page的關係:

page-span.png

看一下span的定義哈:既包含起始頁跟頁數,又有object鍊錶

type mspan struct
1.2 管理元件

tcmalloc 分配器有三種管理元件:

heap中包含一系列不同sizeclass的central,每個central中包含了對應大小的span列表,cache中 以sizeclass為索引管理多個用於分配的span。

image.png

首先是使用者記憶體分配區域,其大小決定了可分配使用者記憶體的上限

其次有乙個點陣圖bitmap,其為每個物件提供4bit標記位,用於保留指標、gc標記等資訊

最後還有乙個頁所屬span指標陣列。

go 記憶體初始化做的工作主要有初始化上面的結構,然後為他們保留位址空間,然後初始化heap的一些其他屬性。在初始化heap的時候,建立了多個不同大小的central。

3.1 tcmalloc分配

過程不複雜,我們畫個流程圖。

分配.png

分析了整體的執行緒記憶體分配流程,那麼當資源不足時如何擴張呢?

資源不足分兩種,第一種是central不足,另一種是heap不足。下面我們從分配的角度,看一下這兩種的流程是什麼樣子的?

3.2 central的分配

central分配.png

其中維持noneempty跟empty鍊錶過程中涉及到了sweepgen,這個用於central 中span的清理。

從central 裡獲取span時,優先取用已有資源。哪怕是要執行清理操作,只有當現有資源不滿足時才會去heap中獲取span。

3.3 heap的分配

heap自己維護了兩個鍊錶,busy跟busylarge,顧名思義,就是按照大小區分的。

在分配時,當是小物件時,放在busy鍊錶供central使用,大物件放在busylarge,放在busylarge鍊錶。

當heap中的記憶體不足時,就只能向作業系統申請了。

3.4 向作業系統申請分配

使用了mmap,從指定位置申請記憶體。需要同步擴張heap的 bitmap和spans區域,以及調整arena_used這個位置指示器。

3.5 總結一下分配過程

**.png

main啟動時會啟動乙個監控任務sysmon,每隔一段時間就會檢查heap中的閒置記憶體塊,如果閒置時間超過閾值,則釋放其關聯的物理記憶體。

1、官方文件

2、自旋鎖

3、《go語言學習筆記》

4、**tcmalloc

C C 記憶體分配機制

1.c語言中的記憶體機制 在c語言中,記憶體主要分為如下5個儲存區 1 棧 stack 位於函式內的區域性變數 包括函式實參 由編譯器負責分配釋放,函式結束,棧變數失效。2 堆 heap 由程式設計師用malloc calloc realloc分配,free釋放。如果程式設計師忘記free了,則會造...

memcached記憶體分配機制

memcached slab allocator分配機制 slab allocator的基本原理是按照預先規定的大小,將分配的記憶體分割成特定長度的塊,以完全解決記憶體碎片問題。slab allocation的原理相當簡單,就是將分配的記憶體分割成各種尺寸的塊 chunk 並把尺寸相同的塊分成組 c...

Memcache記憶體分配機制

1.page 頁 為記憶體分配的最小單位 memcached 的記憶體分配以page為單位,預設情況下乙個page是1m,可以通過 i引數在啟動時指定。如果需要申請記憶體時,memcached會劃分出乙個新的page並分配給需要的slab區域。page一旦被分配在重啟前不會被 或者重新分配 2.sl...