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