TCMalloc的使用與原始碼剖析之二---------TCMalloc記憶體分配與管理簡述
TCMalloc給每個執行緒分配了一個執行緒區域性快取,小物件的分配是直接由執行緒區域性快取來完成的,這樣就避免了多執行緒程式中的鎖競爭情況。當執行緒區域性快取中的記憶體不夠時,會將物件從中央資料結構移動到執行緒區域性快取中,同時定期的用垃圾收集器把記憶體從執行緒區域性快取遷移回中央資料結構中。
TCMalloc將尺寸小於等於256 * 1024位元組的物件(“小”物件)和大物件區分開來。大物件直接使用頁級分配器從中央頁堆直接分配。即,一個大物件總是頁對齊的並佔據了整數個數的頁。
1.小物件的分配
每個小物件的大小都會被對映到與之接近的可分配的class
一個執行緒快取包含了由各個尺寸記憶體的物件組成的單鏈表,如圖所示:
當分配一個小物件時:(1)我們將其大小對映到對應的尺寸中。(2)查詢當前執行緒的執行緒快取中相應的尺寸的記憶體連結串列。(3)如果當前尺寸記憶體連結串列非空,那麼從連結串列中移除的第一個物件並返回它。當我們按照這種方式分配時,
如果當前尺寸記憶體連結串列為空:(1)從Central Cache中取得一系列這種尺寸的物件(CentralCache是被所有執行緒共享的)。(2)將他們放入該執行緒執行緒的緩衝區。(3)返回一個新獲取的物件給應用程式。
如果CentralCache也為空:(1)我們從中央頁堆中分配一系列頁面。(2) 將他們分割成該尺寸的一系列物件。(3)將新分配的物件放入CentralCache的連結串列上 (4) 像前面一樣,將部分物件移入執行緒區域性的連結串列中。
如果中央頁堆也為空,那麼就從系統中分配一系列的頁面
2.大物件的分配
一個大物件的尺寸會被中央頁堆直接處理,被圓整到一個頁面尺寸(4K)。中央頁堆是由空閒記憶體列表組成的陣列。對於i < 256
而言,陣列的第k
個元素是一個由每個單元是由k個頁面組成的空閒記憶體連結串列。第256
個條目則是一個包含了長度>=
256
個頁面的空閒記憶體連結串列:
k個頁面的一次分配通過在第k
個空閒記憶體連結串列中查詢來完成。如果該空閒記憶體連結串列為空,那麼我們則在下一個空閒記憶體連結串列中查詢,如此繼續。最終,如果必要的話,我們將在最後空閒記憶體連結串列中查詢。如果這個動作也失敗了,我們將向系統獲取記憶體(使用sbrk
、mmap
或者通過在/dev/mem
中進行對映)
如果k
個頁面的分配是由連續的> k個頁面的空閒記憶體連結串列完成的,剩下的連續頁面將被重新插回到與之頁面大小接近的空閒記憶體連結串列中去。