前面介紹了bluestore的bitmap分配器,我們知道新版本的bitmap
分配器的優勢在於使用連續的記憶體空間從而盡可能更多的命中cpu cache以提高分配器效能。在這裡我們了解一下基於區間樹的stupid
分配器(類似於linux buddy記憶體管理演算法),並對比分析一下其優劣。
linux記憶體管理演算法為了能夠快速響應請求,盡可能的提高記憶體利用率同時減少外部記憶體碎片,引入了夥伴系統演算法buddy-system
。該演算法將所有的空閒頁分組為11個鍊錶,每個鍊錶分別包含1、2、4、8、16、32、64、128、256、512、1024
個連續的頁框塊,每個頁框塊的第乙個記憶體頁的實體地址是該塊大小的整數倍。夥伴的特點是:兩個塊大小相同、兩個塊位址連續、第一塊的第乙個頁框的實體地址是兩個塊總大小的整數倍(同屬於乙個大塊,第1塊和第2塊是夥伴,第3塊和第4塊是夥伴,但是第2塊和第3塊不是夥伴)。具體記憶體分配和記憶體釋放可自行google。
優點:
缺點:
stupid分配器使用了區間樹組織資料結構,高效管理extent(offset, length)
。
class stupidallocator : public allocator ;
每顆區間樹的下標為index(0-9)
,index(1-9)表示的空間大小為:[2^(index-1) * bdev_block_size, 2^(index) * bdev_block_size)
,
初始化stupid分配器後,呼叫者會向allocator中加入或者刪除空閒空間。
// 增加空閒空間
void stupidallocator::init_add_free(uint64_t offset, uint64_t length)
// 刪除空閒空間
void stupidallocator::init_rm_free(uint64_t offset, uint64_t length)
}num_free -= length; // 更新可用空間
}
區間樹實現**:
insert函式**:
#l445
erase函式**:
#l516
最核心的實現是向區間樹中插入以及刪除區間,**如下:
// 根據區間的長度,選取將要存放的區間樹,長度越大,bin值越大。
unsigned stupidallocator::_choose_bin(uint64_t orig_len)
void stupidallocator::_insert_free(uint64_t off, uint64_t len)
}
回顧第一節夥伴演算法,兩種合併的方式是有區別的:
區間樹刪除extent比較簡單,在原來extent刪除傳入的extent,然後計算最終extent是否落入其他區間樹,如果落入則從此區間樹刪除,加入新的區間樹。
空間分配的函式定義如下:
allocate(uint64_t want_size, uint64_t alloc_unit,
uint64_t max_alloc_size, int64_t hint,pextentvector* extents);
allocate_int(uint64_t want_size, uint64_t alloc_unit, int64_t hint,
uint64_t* offset, uint32_t* length)
其中hint
是乙個很重要的引數,表示分配的起始位址要盡量大於hint的值。核心流程為4個2層for迴圈大致為:優先從hint位址依次向高階區間樹開始分配長度大於等於want_size
的連續空間,如果沒有,則優先從hint位址依次向低階區間樹開始分配長度大於等於alloc_unit
的連續空間(長度會大於alloc_unit)。
簡單的空間分配圖如下:
詳細的空間分配流程圖如下:
空間釋放的函式定義如下:
release(const interval_set&release_set)
流程很簡單,先加鎖,然後迴圈呼叫_insert_free
插入到對應區間樹裡面,會涉及到相鄰空閒空間的合併,但是會導致分配空間碎片的問題。
stupid底層使用btreemap來儲存一系列的extent,記憶體不一定是連續的,同時在分配空間遍歷區間樹時,雖然區間樹裡面的extent是有序的,但是由於記憶體不一定是連續或者相鄰的兩個extent記憶體跨度可能很大,都會導致cpu-cache預讀不到下乙個extent,從而不能很好的利用cpu-cache。
bitmap分配器在bluestore初始化時就初始化好了3層,而且大小是固定的,同時分配空間是依次順序分配,從而可以充分的利用cpu-cache的功能。從而提高分配器的效能。
基於extent的stupid分配器存在偽空間碎片(物理空間是連續的,但是分配器中卻不連續)問題:
乙個24k的連續空間,經過6次4k分配和亂序的6次4k釋放後,可能會變成8k + 4k + 8k + 4k
四塊空間。
其中兩個4k的區間由於和周邊塊大小一樣,所以落到不同的區間樹中,導致很難被合併,24k的連續空間變成了四塊不連續空間。
bitmap分配器由於初始化時就分配好了3層所有記憶體,而且3層都是有序的的同時分配空間是順序遍歷的,在釋放空間的時候設定相應位就可以,不影響連續性,所以不存在這個問題。
據bitmap作者的效能對比實驗來看,bitmap分配器要好於stupid,等bitmap穩定後,可以設定bluestore的預設分配器為bitmap。
新購雲服務1月5折 3月4.5折 6月低至4折
滴滴雲使者招募,推薦最高返傭50%
滴滴雲-為開發者而生
滴滴雲使者
原始碼分析之LayoutInflater
簡介 inflate填充的過程 viewstub,merge,include的載入過程 layoutinflater系統服務的註冊過程 systemserviceregistry類有個靜態 塊,完成了常用服務的註冊,如下 static 註冊am registerservice context.act...
原始碼分析之HashMap
首先hashmap繼承了abstractmap,並且實現了map cloneable和serializable三個介面。cloneable和serializable是比較常規的兩個介面,在這裡並不作為重點。重點將會放在abstractmap和map兩個規範上。其中abstractmap是乙個抽象類,...
原始碼分析之String
先看屬性 底層是char陣列,一目了然 可以看到,value是儲存string的內容的,即當使用string str abc 的時候,本質上,abc 是儲存在乙個char型別的陣列中的。string底層的儲存結構是乙個字元型別的陣列,同樣也是被final修飾,因此一旦這個字元陣列被建立後,value...