一:
slab是為了解決內部碎片提出的,還是外部碎片?
為了解決內部碎片。
內部碎片的產生:因為所有的內存分配必須起始於可被 4、8 或 16 整除(視處理器體系結構而定)的地址或者因為MMU的分頁機制的限制,決定內存分配算法僅能把預定大小的內存塊分配給客戶。假設當某個客戶請求一個 43 字節的內存塊時,因為沒有適合大小的內存,所以它可能會獲得 44字節、48字節等稍大一點的字節,因此由所需大小四舍五入而產生的多余空間就叫內部碎片。
外部碎片的產生: 頻繁的分配與回收物理頁面會導致大量的、連續且小的頁面塊夾雜在已分配的頁面中間,就會產生外部碎片。假設有一塊一共有100個單位的連續空閑內存空間,范圍是0~99。如果你從中申請一塊內存,如10個單位,那么申請出來的內存塊就為0~9區間。這時候你繼續申請一塊內存,比如說5個單位大,第二塊得到的內存塊就應該為10~14區間。如果你把第一塊內存塊釋放,然后再申請一塊大於10個單位的內存塊,比如說20個單位。因為剛被釋放的內存塊不能滿足新的請求,所以只能從15開始分配出20個單位的內存塊。現在整個內存空間的狀態是0~9空閑,10~14被占用,15~24被占用,25~99空閑。其中0~9就是一個內存碎片了。如果10~14一直被占用,而以后申請的空間都大於10個單位,那么0~9就永遠用不上了,變成外部碎片。
二:
slab算法的核心思想是什么?
slab的核心思想是以對象的觀點來管理內存。
內核對其對象的使用具有以下特殊性:
- 內核使用的對象種類繁多,應該采用一種統一的高效管理方法。
- 內核對某些對象(如 task_struct)的使用是非常頻繁的,所以用戶進程堆管理常用的基於搜索的分配算法比如First-Fit(在堆中搜索到的第一個滿足請求的內存塊)和 Best-Fit(使用堆中滿足請求的最合適的內存塊)並不直接適用,而應該采用某種緩沖區的機制。
- 內核對象中相當一部分成員需要某些特殊的初始化(例如隊列頭部)而並非簡單地清成全 0。如果能充分重用已被釋放的對象使得下次分配時無需初始化,那么可以提高內核的運行效率。
- 分配器對內核對象緩沖區的組織和管理必須充分考慮對硬件高速緩存的影響。
- 隨着共享內存的多處理器系統的普及,多處理器同時分配某種類型對象的現象時常發生,因此分配器應該盡量避免處理器間同步的開銷,應采用某種 Lock-Free 的算法。
所以,這就需要slab機制以對象的觀點來解決小內存問題。
三:有關slab的着色問題
着色與硬件cache有關,這就牽扯到cache和主存的工作結構:
- 全相連
- 任一主存塊能映射到任意緩存行(主存塊的大小等於緩存行的大小。
- 優點:靈活,不易產生沖突
- 缺點:比較電路難於實現,且效率低,速度慢
- 直接映射
- 某一主存塊只能映射到特定的緩存行
- 優點:硬件簡單,成本低
- 缺點:容易產生沖突,易產生緩存“顛簸”,不能有效利用cache空間
- 組相聯
- 組間直接映射,組內全相聯映射
- 優點:結合上面兩種的優點
- 因為組內行數較少,比較器容易實現
- 組內又有靈活性,沖突大大減小
由上可知,slab着色對於直接映射和組相連映射的工作結構效率幫助較大,而全項鏈結構本身沖突就比較小,那么着色的幫助是很小的。在全相連工作結構中,使用着色無疑是一個巨大的內存浪費。
slab算法的缺點
隨着大規模多處理器系統和NUMA系統的廣泛應用,slab分配器逐漸暴露出自身嚴重的不足:
- 較多復雜的隊列管理。在slab分配器中存在眾多的隊列,例如針對處理器的本地緩存隊列,slab中空閑隊列,每個slab處於一個特定狀態的隊列之中。所以,管理太費勁了。
- slab管理數據和隊列的存儲開銷比較大。每個slab需要一個struct slab數據結構和一個管理者kmem_bufctl_t型的數組。當對象體積較小時,該數組將造成較大的開銷(比如對象大小為32字節時,將浪費1/8空間)。為了使得對象在硬件告訴緩存中對齊和使用着色策略,還必須浪費額外的內存。同時,緩沖區針對節點和處理器的隊列也會浪費不少內存。測試表明在一個1000節點/處理器的大規模NUMA系統中,數GB內存被用來維護隊列和對象引用。
- 緩沖區回收比較復雜。
- 對NUMA的支持非常復雜。slab對NUMA的支持基於物理頁框分配器,無法細粒度的使用對象,因此不能保證處理器級的緩存來自同一節點(這個我暫時不太懂)。
- 冗余的partial隊列。slab分配器針對每個節點都有一個partial隊列,隨着時間流逝,將有大量的partial slab產生,不利於內存的合理使用。
- 性能調優比較困難。針對每個slab可以調整的參數比較復雜,而且分配處理器本地緩存時,不得不使用自旋鎖。
- 調試功能比較難於使用。
為了解決以上slab分配器的不足,引入新的解決方案,slub分配器。slub分配器的特點是簡化設計理念,同時保留slab分配器的基本思想:每個緩沖區有多個slab組成,每個slab包含固定數目的對象。slub分配器簡化了kmem_cache,slab等相關的管理結構,擯棄了slab分配器中的眾多隊列概念,並針對多處理器、NUMA系統進行優化,從而提高了性能和可擴展性並降低了內存的浪費。並且,為了保證內核其他模塊能無縫遷移到slub分配器,API接口函數與slab保持一致。
缺點簡單說就是:
- 緩存隊列管理復雜;
- 管理數據存儲開銷大;
- 對NUMA支持復雜;
- 調試調優困難;
- 摒棄了效果不太明顯的slab着色機制;
過些天就開始剖析slub分配器,不過由於有slab的基礎,那個已經是小菜了。