LevelDB 原始碼解析之 Arena

2022-07-12 18:42:18 字數 2830 閱讀 8650

github:

emai: [email protected]

華為雲社群:

leveldb:

記憶體池的存在主要就是減少呼叫malloc或者new的次數,減少記憶體分配所帶來的系統開銷,提公升效能。

leveldb 中的記憶體池是由類arena實現的。arena先向系統申請一塊大的記憶體,當其他元件需要申請記憶體時,arena先將已有的記憶體塊分配給元件,如果不夠用則再申請一塊大的記憶體。當記憶體池物件析構時,分配的記憶體均被釋放,這保證了記憶體不會洩漏。

申請記憶體和分配記憶體的區別:

// 指向當前記憶體塊未分配記憶體的起始位址的指標

char* alloc_ptr_;

// 記錄當前記憶體塊未分配記憶體的大小

size_t alloc_bytes_remaining_;

// 每個記憶體塊的位址都儲存在 vector 中

std::vectorblocks_;

// 原子變數:記錄當前物件的記憶體總量

std::atomicmemory_usage_;

如圖所示,arena的成員變數blocks_儲存若干個指標,每個指標指向一塊記憶體。alloc_ptr_指向當前記憶體塊未分配記憶體的起始位址,alloc_bytes_remaining_為當前記憶體塊未分配記憶體的大小。

static const int kblocksize = 4096;
arena以記憶體塊為單位來管理記憶體,每個記憶體塊的大小kblocksize為 4096 kb。

arena::arena()

: alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {}

arena::~arena()

}

建構函式初始化所有的成員變數,保證不會使用未初始化的變數。

析構函式釋放blocks_中每個指標指向的記憶體塊。

arena提供了 3 個public函式來簡化記憶體分配。

arena的記憶體分配策略有三種,當申請bytes大小的記憶體時:

inline char* arena::allocate(size_t bytes) 

// 申請的記憶體大於當前記憶體塊剩餘的記憶體,使用 allocatefallback 函式重新申請記憶體

return allocatefallback(bytes);

}

allocate函式分配bytes大小的記憶體空間,返回指向所分配記憶體的指標。

char* arena::allocatealigned(size_t bytes)  else 

// 保證分配的記憶體起始位址是位元組對齊的

assert((reinterpret_cast(result) & (align - 1)) == 0);

return result;

}

allocatealigned函式分配bytes大小的記憶體空間,且起始位址位元組對齊,返回指向所分配記憶體的指標。

size_t memoryusage() const
memoryusage函式返回當前分配給arena物件的所有記憶體空間大小和所有指向記憶體塊的指標大小之和。

接上節中的arena的記憶體分配策略,當申請bytes大小的記憶體時:

char* arena::allocatefallback(size_t bytes) 

// 呼叫 allocatenewblock 申請一塊大小為 kblocksize 的新記憶體塊

alloc_ptr_ = allocatenewblock(kblocksize);

alloc_bytes_remaining_ = kblocksize;

// 在新申請的記憶體塊中分配 bytes 大小的記憶體

char* result = alloc_ptr_;

alloc_ptr_ += bytes;

alloc_bytes_remaining_ -= bytes;

return result;

}

當申請的記憶體大於當前記憶體塊剩餘記憶體時,allocatefallback函式會被呼叫,用來按照後兩種分配策略分配記憶體。

這兩種分配策略可以進一步減少記憶體分配的次數,但同時每塊最後 \(\frac\) 的空間有可能會被浪費。

char* arena::allocatenewblock(size_t block_bytes)
allocatenewblock函式申請乙個大小為block_bytes的記憶體塊。

當向arena申請bytes大小的記憶體時:

LevelDB原始碼剖析之Memtable 1

memtable是leveldb很重要的一塊,leveldb的核心之一。我們肯定關注kv資料在memtable中是如何組織的,秘密在skip list中。在leveldb中,所有記憶體中的kv資料都儲存在memtable中,物理disk則儲存在sstable中。在系統執行過程中,如果memtable...

leveldb原始碼分析之Arena

arena 是 leveldb 專案裡面使用的輕量級的記憶體池物件,leveldb 用這個物件來管理記憶體的分配,簡化了 new 和 delete 的呼叫,我們也可以從這個輕量級的記憶體池物件學習 google 大神工程師是如何管理記憶體的。arena 記憶體管理模型 arena 使用下面幾個成員變...

leveldb原始碼分析之SSTable檔案例項講解

sstable檔案是memtable 資料到一定閾值寫入檔案形成的,由於記憶體容量總是有限的,將一定量資料寫入磁碟可以存放更多資料,所以leveldb相比redis能存放更多資料。既然資料持久化到磁碟,那麼還有必然涉及到從磁碟中查詢資料,從磁碟中查詢資料與從記憶體中查詢資料的效率是不一樣的,所以ss...