arena 是 leveldb 專案裡面使用的輕量級的記憶體池物件,leveldb 用這個物件來管理記憶體的分配,簡化了 new 和 delete 的呼叫,我們也可以從這個輕量級的記憶體池物件學習 google 大神工程師是如何管理記憶體的。
arena 記憶體管理模型
arena 使用下面幾個成員變數來描述上面的模型圖
在開始分析之前你需要了解申請記憶體和分配記憶體的區別:// 當前記憶體塊未分配記憶體的起始位址
char* alloc_ptr_;
// 當前記憶體塊剩餘的記憶體
size_t alloc_bytes_remaining_;
// arena 使用 vector 來儲存每個記憶體塊的位址
std::vectorblocks_;
// 當前 arena 已經分配的總記憶體量
port::atomicpointer memory_usage_;
申請記憶體:使用 new 來向作業系統申請一塊連續的記憶體區域。
分配記憶體:將已經申請的記憶體分配給專案元件使用,這體現在增加 alloc_ptr_ 和減少 alloc_bytes_remaining_ 這兩個指標上。
為什麼要強調這兩個概念呢?
因為 arena 是乙個記憶體池,他的功能就是記憶體的管理,包括申請記憶體,分配記憶體,釋放記憶體。
arena 的構造和析構
arena 提供的介面函式arena 給我們提供了 3 個 public 函式來簡化我們的記憶體訪問// 良好的初始化風格
arena::arena() : memory_usage_(0)
arena::~arena()
}
allocate這是乙個最重要的記憶體分配函式,這個函式會根據你要申請的記憶體大小來呼叫另外兩個私有的記憶體分配函式public:
// 基本的記憶體分配函式
char* allocate(size_t bytes);
// 按照位元組對齊來分配記憶體
char* allocatealigned(size_t bytes);
// 返回目前分配的總的記憶體
size_t memoryusage() const;
allocatefallback在申請的記憶體大於當前塊剩餘記憶體時,allocatefallback會被呼叫,它提供 2 種申請記憶體的策略:inline char* arena::allocate(size_t bytes)
// 申請的記憶體的大於當前記憶體塊剩餘的記憶體,就用這個函式來重新申請記憶體
return allocatefallback(bytes);
}
假如我當前塊剩餘 900 kb 記憶體,而我需要申請 1200 kb 記憶體,如果我直接申請一塊大小為 1200 kb 的記憶體塊,就只需要申請一次;但是如果我在當前塊先分配 900 kb 記憶體,然後再申請乙個新的 4096 kb 的記憶體塊,再在裡面分配 1200 - 900 = 300 kb 的記憶體,這樣就需要申請 1 次記憶體,分配兩次記憶體,效率低下了不少(在分配比較頻繁的時候),因此這樣直接申請並分配乙個 bytes 大小的記憶體塊非常高效方便。
allocatenewblock這是 allocatenewblock 的實現,它就是簡單的申請了乙個 block_bytes 大小的記憶體塊// bytes 代表實際要申請的記憶體大小
char* arena::allocatefallback(size_t bytes)
// bytes < 1 / 4 (1024 kb),申請乙個預設大小為 4096 kb 的記憶體塊
alloc_ptr_ = allocatenewblock(kblocksize);
alloc_bytes_remaining_ = kblocksize;
// 在申請的預設大小的記憶體塊裡分配 bytes 位元組記憶體
char* result = alloc_ptr_;
alloc_ptr_ += bytes;
alloc_bytes_remaining_ -= bytes;
return result;
}
char* arena::allocatenewblock(size_t block_bytes)
allocatealigned這個函式可以分配位元組對齊的記憶體,實現稍微有些複雜,不過仔細分析還是有很多營養的,注釋很詳細
char* arena::allocatealigned(size_t bytes) else
assert((reinterpret_cast(result) & (align-1)) == 0);
return result;
}
leveldb原始碼分析之SSTable檔案例項講解
sstable檔案是memtable 資料到一定閾值寫入檔案形成的,由於記憶體容量總是有限的,將一定量資料寫入磁碟可以存放更多資料,所以leveldb相比redis能存放更多資料。既然資料持久化到磁碟,那麼還有必然涉及到從磁碟中查詢資料,從磁碟中查詢資料與從記憶體中查詢資料的效率是不一樣的,所以ss...
leveldb原始碼分析 之 入門使用
leveldb是google開源的乙個key value儲存引擎庫,類似於開源的lucene索引庫一樣。其他的軟體開發者可以利用該庫做二次開發,來滿足定製需求。leveldb採用日誌式的寫方式來提高寫效能,但是犧牲了部分讀效能。為了彌補犧牲了的讀效能,一些人提議使用ssd作為儲存介質。對於本地化的k...
leveldb原始碼分析1
leveldb是乙個key value型的儲存引擎,由google開發,並宣布在bsd許可下開放源 plain git clone plain cd leveldb make all 此時生成libleveldb.a庫檔案。拷貝leveldb的標頭檔案到 usr include下 plain cp ...