天天看點

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

(1)第一層,線程局部配置設定,ThreadCache

       ThreadCache包含了一個不同對象大小的空閑連結清單數組,其實作采用作業系統的線程局部存儲功能。配置設定時幾乎不需要用鎖,除非觸發CentralCache的操作。

ThreadCache中的重要資料結構:

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

pthread_t     tid_;   綁定線程,達到每個線程有個緩沖池的目的

FreeList      list_[kNumClasses];  這個數組就是上圖中的第一列,如下圖

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

數組中的每一個節點就是代表上圖中的每一行,如下圖

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

每個class對應多大的記憶體空間?這個表示每組的大小的變量在哪裡?

不存在這樣的變量,但是通過映射關系可以達到一個class管一類size的作用,

如下圖所示,由cl 得到list_[cl],這也即是一個class。

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

至于cl,是由class_array_得到的,關于這個内容在第五章:幾個重要的資料結構

若申請的記憶體是13位元組,但配置設定的卻是15位元組,那麼便會有2個位元組的記憶體碎片(内部碎片)。

(2)第二層 ,中心配置設定,Centralcache

該層的配置設定需要鎖。CentralCache和ThreadCache之間的空閑連結清單是一一對應的,以子連結清單為機關(obj個數很可能為num_objects_to_move(cl),見do_malloc與do_free流程圖)進行互相交換。

CentralCache的記憶體從PageHeap裡獲得。從PageHeap獲得的記憶體叫Span。一個Span在使用時隻能用于同一大小的空閑連結清單,一但CentralCache從PageHeap中擷取新的Span,這個Span就是一個串好的相同大小記憶體的空閑連結清單。

Centralcache中有幾個重要資料結構:

1.     TCEntry  tc_slots_[kMaxNumTransferEntries];

tc_slots_每個節點存放的是一組obj連結清單,這一組obj的個數為num_objects_to_move,TCEntry結構體有兩指針,分别指向這個連結清單的頭和尾。

tc_slots_存放的是threadCache向CentralCache歸還的obj連結清單,并且隻有當個數滿足num_objects_to_move時,才會放入tc_slots_。否則歸還的obj根據其所處的span,進行歸還,若對應的span是empty,那麼由于此時被歸還記憶體了,是以其有空閑obj了,便把該span從empty隊列清除,把其加入nonempty隊列。

2.      span empty

FetchFromSpans函數把一個obj從nonempty隊列中的一個span中切出,準備給threadCache。當切完這個obj後,如果該span已經沒有記憶體空間了,那麼便把該span從nonempty隊列移除,并加入empty隊列。

3.     span nonempty

CentralCache從中央頁堆申請頁面,中央頁堆以span的形式傳回。在CentralCache中會把該span切成大小為class_to_size的obj,并把所有的obj連結起來,連結清單頭為span->objects。再把該連結清單加入nonempty隊列。

Nonempty隊列另外一個被加入span的地方在記憶體從threadCache歸還給CentralCache時,具體情況見上面”tc_slots_”這一資料結構的描述。

(3)第三層,中央頁堆,PageHeap

       PageHeap以一定數量連續頁面記憶體的形式提供記憶體。這組連續的頁面由一個Span對象描述,Span對象和它描述的頁面記憶體是獨立的。Span對象儲存了頁面的id序列,頁面id左移一個page就是記憶體的位址。由于頁面和Span記憶體獨立,需要用page id反向映射查找Span對象就需要單獨的映射表。這個表用radix tree實作,兼顧效率和記憶體。PageHeap還負責合并和拆分相鄰的Span。

PageHeap重要資料結構:

SpanList   large_;

SpanList   free_[kMaxPages];

中央頁堆是由空閑記憶體清單組成的數組。對于i< 256而言,數組的第k個元素是一個由每個單元是由k個頁面組成的空閑記憶體連結清單(這也即是free_)。第256個條目(這即是large_)則是一個包含了長度>= 256個頁面的空閑記憶體連結清單:

TCMalloc的使用與源碼剖析之三---------TCMalloc的記憶體配置設定的主要層次

而SpanList為

struct SpanList {

    Span       normal;

    Span       returned;

  };

Returned代表的是已經歸還給系統的span

(4)第四層,系統頁面配置設定,

這就是調用系統函數了。

繼續閱讀