1. 程式人生 > >TCMalloc的使用與原始碼剖析之二---------TCMalloc記憶體分配與管理簡述

TCMalloc的使用與原始碼剖析之二---------TCMalloc記憶體分配與管理簡述

        TCMalloc給每個執行緒分配了一個執行緒區域性快取,小物件的分配是直接由執行緒區域性快取來完成的,這樣就避免了多執行緒程式中的鎖競爭情況。當執行緒區域性快取中的記憶體不夠時,會將物件從中央資料結構移動到執行緒區域性快取中,同時定期的用垃圾收集器把記憶體從執行緒區域性快取遷移回中央資料結構中。

         TCMalloc將尺寸小於等於256 * 1024位元組的物件(物件)和大物件區分開來。大物件直接使用頁級分配器從中央頁堆直接分配。即,一個大物件總是頁對齊的並佔據了整數個數的頁。

1.小物件的分配

        每個小物件的大小都會被對映到與之接近的可分配的class

中的一個。例如,所有大小在8331024位元組之間的小物件時,都會歸整到1024位元組。60個可分配的尺寸類別這樣隔開:較小的尺寸相差8位元組,較大的尺寸相差16位元組,再大一點的尺寸差32位元組,如此等等。最大的間隔是控制的,這樣剛超過上一個級別被分配到下一個級別就不會有太多的記憶體被浪費。

一個執行緒快取包含了由各個尺寸記憶體的物件組成的單鏈表,如圖所示:

        

        當分配一個小物件時:(1)我們將其大小對映到對應的尺寸中。2)查詢當前執行緒的執行緒快取中相應的尺寸的記憶體連結串列。3)如果當前尺寸記憶體連結串列非空,那麼從連結串列中移除的第一個物件並返回它。當我們按照這種方式分配時,

TCMalloc不需要任何鎖。這就可以極大提高分配的速度,因為鎖/解鎖操作在一個2.8GHzXeon上大約需要100納秒的時間。

如果當前尺寸記憶體連結串列為空:(1)從Central Cache中取得一系列這種尺寸的物件(CentralCache是被所有執行緒共享的)。2)將他們放入該執行緒執行緒的緩衝區3)返回一個新獲取的物件給應用程式。

如果CentralCache也為空:(1)我們從中央頁堆中分配一系列頁面。(2) 將他們分割成該尺寸的一系列物件。(3)將新分配的物件放入CentralCache的連結串列上 (4) 像前面一樣,將部分物件移入執行緒區域性的連結串列中。

如果中央頁堆也為空,那麼就從系統中分配一系列的頁面

(使用sbrkmmap或者通過在/dev/mem中進行對映),把頁面給中央頁堆,然後繼續上面的操作

2.大物件的分配

一個大物件的尺寸會被中央頁堆直接處理,被圓整到一個頁面尺寸(4K)。中央頁堆是由空閒記憶體列表組成的陣列。對於i < 256而言,陣列的第k個元素是一個由每個單元是由k個頁面組成的空閒記憶體連結串列。第256個條目則是一個包含了長度>= 256個頁面的空閒記憶體連結串列:

  

k個頁面的一次分配通過在第k個空閒記憶體連結串列中查詢來完成。如果該空閒記憶體連結串列為空,那麼我們則在下一個空閒記憶體連結串列中查詢,如此繼續。最終,如果必要的話,我們將在最後空閒記憶體連結串列中查詢。如果這個動作也失敗了,我們將向系統獲取記憶體(使用sbrkmmap或者通過在/dev/mem中進行對映)

如果k個頁面的分配是由連續的> k個頁面的空閒記憶體連結串列完成的,剩下的連續頁面將被重新插回到與之頁面大小接近的空閒記憶體連結串列中去。