多年以來,Linux 內核使用一種稱為SLAB 的內核對象緩沖區(qū)分配器。但是,隨著系統(tǒng)規(guī)模的不斷增大,SLAB 逐漸暴露出自身的諸多不足。SLUB 是 Linux 內核 2.6.22 版本中引入的一種新型分配器,它具有設計簡單、代碼精簡、額外內存占用率小、擴展性高,性能優(yōu)秀、方便調試等特點。
SLAB 分配器多年以來一直位于 Linux 內核的內存管理部分的核心地帶,內核黑客們一般不愿意主動去更改它的代碼,因為它實在是非常復雜,而且在大多數(shù)情況下,它的工作完成的相當不錯。但是,隨著大規(guī)模多處理器系統(tǒng)和 NUMA系統(tǒng)的廣泛應用,SLAB 分配器逐漸暴露出自身的嚴重不足:
較多復雜的隊列管理。在 SLAB 分配器中存在眾多的隊列,例如針對處理器的本地對象緩存隊列,slab 中空閑對象隊列,每個 slab 處于一個特定狀態(tài)的隊列中,甚至緩沖區(qū)控制結構也處于一個隊列之中。有效地管理這些不同的隊列是一件費力且復雜的工作。slab 管理數(shù)據(jù)和隊列的存儲開銷比較大。每個 slab 需要一個 struct slab 數(shù)據(jù)結構和一個管理所有空閑對象的 kmem_bufctl_t(4 字節(jié)的無符號整數(shù))的數(shù)組。當對象體積較少時,kmem_bufctl_t 數(shù)組將造成較大的開銷(比如對象大小為32字節(jié)時,將浪費 1/8 的空間)。為了使得對象在硬件高速緩存中對齊和使用著色策略,還必須浪費額外的內存。同時,緩沖區(qū)針對節(jié)點和處理器的隊列也會浪費不少內存。測試表明在一個 1000 節(jié)點/處理器的大規(guī)模 NUMA 系統(tǒng)中,數(shù) GB 內存被用來維護隊列和對象的引用。緩沖區(qū)內存回收比較復雜。對 NUMA 的支持非常復雜。SLAB 對 NUMA 的支持基于物理頁框分配器,無法細粒度地使用對象,因此不能保證處理器級緩存的對象來自同一節(jié)點。冗余的 Partial 隊列。SLAB 分配器針對每個節(jié)點都有一個 Partial 隊列,隨著時間流逝,將有大量的 Partial slab 產生,不利于內存的合理使用。性能調優(yōu)比較困難。針對每個 slab 可以調整的參數(shù)比較復雜,而且分配處理器本地緩存時,不得不使用自旋鎖。調試功能比較難于使用。為了解決以上 SLAB 分配器的不足之處,內核開發(fā)人員 Christoph Lameter 在 Linux 內核 2.6.22 版本中引入一種新的解決方案:SLUB 分配器。SLUB 分配器特點是簡化設計理念,同時保留 SLAB 分配器的基本思想:每個緩沖區(qū)由多個小的 slab 組成,每個 slab 包含固定數(shù)目的對象。SLUB 分配器簡化了kmem_cache,slab 等相關的管理數(shù)據(jù)結構,摒棄了SLAB 分配器中眾多的隊列概念,并針對多處理器、NUMA 系統(tǒng)進行優(yōu)化,從而提高了性能和可擴展性并降低了內存的浪費。為了保證內核其它模塊能夠無縫遷移到 SLUB 分配器,SLUB 還保留了原有 SLAB 分配器所有的接口 API 函數(shù)。