【leveldb】arena内存结构

本文介绍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内存结构】

    推荐阅读