本文介绍arena内存管理的设计和实现。
arena是leveldb中一个非常简单的内存池,以下做详细介绍。
1 数据结构
arena数据结构如下,其中,blocks_保存着所有创建的block;blocks_memory_保存所有block申请的总空间;alloc_ptr_和alloc_bytes_remaining_分别是当前block的内存分配起始地址 和 可用空间大小。
// Allocation state
char* alloc_ptr_;
size_t alloc_bytes_remaining_;
// Array of new[] allocated memory blocks
std::vector blocks_;
// Bytes of memory in blocks allocated so far
size_t blocks_memory_;
2 分配内存
inline char* Arena::Allocate(size_t bytes) {
// The semantics of what to return are a bit messy if we allow
// 0-byte allocations, so we disallow them here (we don't need
// them for our internal use).
assert(bytes > 0);
if (bytes <= alloc_bytes_remaining_) {
char* result = alloc_ptr_;
alloc_ptr_ += bytes;
alloc_bytes_remaining_ -= bytes;
return result;
}
return AllocateFallback(bytes);
}
// Allocate memory with the normal alignment guarantees provided by malloc
char* AllocateAligned(size_t bytes);
char* Arena::AllocateFallback(size_t bytes) {
if (bytes > kBlockSize / 4) {
// Object is more than a quarter of our block size.Allocate it separately
// to avoid wasting too much space in leftover bytes.
char* result = AllocateNewBlock(bytes);
return result;
}// We waste the remaining space in the current block.
alloc_ptr_ = AllocateNewBlock(kBlockSize);
alloc_bytes_remaining_ = kBlockSize;
char* result = alloc_ptr_;
alloc_ptr_ += bytes;
alloc_bytes_remaining_ -= bytes;
return result;
}char* Arena::AllocateNewBlock(size_t block_bytes) {
char* result = new char[block_bytes];
blocks_memory_ += block_bytes;
blocks_.push_back(result);
return result;
}
内存分配由Allocate方法完成,可以使用AllocateAligned获得一个大小对齐的内存。Allocate方法首先根据alloc_bytes_remaining_判断当前block剩余空间是否足够,足够则直接在当前block申请。不足时,判断所需空间的大小,如果大于1/4的blocksize,就当做一个单独的block进行申请;小于等于1/4的blocksize时,申请一个新的block,从新的block中分配内存。因为当单独作为一个block进行申请的时候,alloc_ptr_和alloc_bytes_remaining_指向的block并没有改变,也就是当前block剩余空间仍然可用,所以这样做可以减少内存浪费,对于每个block,最多不超过1/4的blocksize的内存会被浪费掉。这个blocksize设定为4096。
3 释放内存
Arena::Arena() {
blocks_memory_ = 0;
alloc_ptr_ = NULL;
// First allocation will allocate a block
alloc_bytes_remaining_ = 0;
}Arena::~Arena() {
for (size_t i = 0;
i < blocks_.size();
i++) {
delete[] blocks_[i];
}
}
内存只有在arena对象被销毁的时候,才能统一释放。所以Arena内存只能增长。
【【leveldb】arena内存结构】