這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
tcmalloc
tcmalloc 優點
- 速度更快,比glicbc 2.3 快
- 佔用更少的記憶體空間,8倍8-byte的對象記憶體配置中佔用大約8N*1.01byte的頭空間,而ptmalloc則會佔用16N*byte的頭空間
使用
- 在程式中只需使用“-ltmalloc”串連標識將其連結到程式中
綜述
- TCMalloc為每一個線程分配本機快取,以滿足小對象分配的需求,當需要時候,對象從中央資料結構移動到本機快取,周期性的記憶體回收則將記憶體從各個線程的本機快取收回中央資料結構。
小對象分配
- 每個小對象映射到170個不同的大小空間。每個空間間隔8byte,0-8byte(8),8-24byte(16),24-48byte(24),最大間隔為256byte。大對象和小對象的界限為32kb。每個線程的緩衝包括一系列大小不同的空閑對象串連到一起的鏈表。
- 分配一個小對象時
- 先由其大小映射到對應的空間集合
- 尋找當前線程線程緩衝閒置鏈表
- 若果閒置鏈表非空,則取出第一個對象返回給調用者,通過這樣擷取空間時,TCMalloc不需要加鎖。加鎖和解鎖這一對操作在2.8 GHz Xeon處理器上會佔用100納秒的時間,因此這樣的機制可以很有效加速記憶體配置的效率。
- 若鏈表為空白,則從中央空閑鏈中取出一些對象填充到對應的集合中(中央空閑鏈對所有線程共用)。
- 將其放到執行緒區域的空閑鏈
- 返回這些新對象給調用程式。
- 如果中央緩衝區空閑鏈也為空白;
- 向中央頁分配器申請連續的頁
- 把頁分割為一系列大小不同的對象
- 把這些對象放入中央空閑鏈表
- 把其中而一些對象放入執行緒區域緩衝。
大對象分配
- 一個大對象的大小(大於32K)要向上按照頁大小(4K)對齊,並且是由中央的頁面堆來處理。中央頁面堆同樣也是由一些不同大小的元素的鏈表組成的數組。對於i小於256,數組中第k的入口,是由k個頁組成的元素所連結在一起的空閑鏈表。第256個入口是由長度大於256個頁連結在一起的空閑鏈表。
- 一個需要k個頁面大小的分配請求,可以通過訪問第k個空閑鏈表來滿足。如果該空閑鏈表為空白,我們就訪問下一個空閑鏈表(頁面大一些的),以此類推。最終,如果需要的話我們會訪問最後一個空閑鏈。如果這一系列的尋找都失敗的話,我們將從系統中得到記憶體(使用sbrk,mmap或者通過映射一部分/dev/mem)。如果一個k頁面大小的分配請求分配到的記憶體空間大於k個頁面,當該空間釋放的時候需要放回到頁面堆中相應大小的空閑鏈表中。
Spans
- TCMalloc的堆管理機制是將一些頁面集合,一組連續的頁面的結合稱為一個span對象。span既可以被分配也可以被釋放。如果被釋放,span將會被放到對應的頁面堆鏈表。如果被分配,span可以是一個交給應用程式的大對象,或者是一組被分割成連續小對象的頁面。如果是被分割成為小對象,那麼在span中會記錄對象的大小層級。中央數組的頁號索引,能夠用於實現找到一個Span由哪些頁面組成。舉例來說,的span a佔有2個頁面,spanb佔有1個頁面,span c佔有5個頁面,而span d佔有3個頁面。
- 一個32位的地址空間能夠分配2^20個4K的頁面,因此中央數組佔據4MB的記憶體空間是可以令人接受的。在64位的機器上,我們使用3級的基樹來代替數組,用於映射頁號與對應的span指標。
對象釋放
- 對象釋放時,計算機頁好並在中央數組尋找其對應的span。span中包含對象的資訊,可以得知對象是否為小對象。如果是小對象,則放回線程緩衝的空閑鏈表中。如果線程的緩衝超出預定大小(預設2MB),則運行垃圾收集器把當前線程不用的對象放回central的freelist。
- 如果釋放對象是大對象,通過span可以擷取對象包含頁範圍。通過頁範圍尋找範圍的上下限,如果上下限的頁也為空白閑的,則將其一起放到heap的頁管理器中。
小對象中央空閑鏈
- 每一個中央空閑鏈包含二級資料結構:一系列的span以及span中的空閑對象組成的空閑鏈表。
- 中央空閑鏈表指派至時,通過移動某個span的鏈表到第一個對象實現的,如果所有spa都有閒置鏈表,則選擇大小合適的span進行分配。
- 一個對象返回到中央空閑鏈,是通過將其掛到span所屬的鏈表中實現的。若鏈表的長度與span中所有的小對象的個數完全相等,該span是完全閒置,並且需要返回到頁堆中。
線程緩衝記憶體回收
- 當線程緩衝中所有空閑對象的帶下超過2MB的時候,記憶體回收期會自動進行回收,線程數增加時候,記憶體回收的閾值會減少以避免記憶體的浪費。
- 我們遍曆緩衝中的所有空閑鏈表,從中移動一定數量的對象到對應的中央鏈表中。每個鏈的低水位標記L決定了從空閑鏈中移出對象的數量。L記錄了自從上一次垃圾收集操作之後本鏈的最小長度。注意我們可以縮短鏈的長度,通過在前一次垃圾收集時移走L個對象,並且沒有從中央鏈中擷取其他對象。我們使用這個過去的記錄來預測未來的情況,從線程緩衝中移走L/2個對象到中央鏈中。這個演算法效能良好,如果一個線程停止使用某個特定大小的對象,該大小的所有對象將會很快的從線程緩衝中遷移到中央空閑鏈中,以便被其他線程來使用。
參考內容