【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)