天天看點

【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<char*> 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記憶體隻能增長。

繼續閱讀