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