1. 程式人生 > >leveldb原始碼-----資料結構之Arena

leveldb原始碼-----資料結構之Arena

leveldb中的記憶體管理主要是通過Arena。Arena管理記憶體的思想是用一個vector來管理申請的block

// Array of new[] allocated memory blocks
std::vector<char*> blocks_;

每個block的大小為4096Byte。

用char*型別的alloc_ptr_指向block中可用的剩餘記憶體的首地址,size_t型別的alloc_bytes_remaining_管理block中剩餘記憶體的數量。

// Allocation state
char* alloc_ptr_;  // 剩餘可分配的記憶體的首地址
size_t alloc_bytes_remaining_;  // 剩餘記憶體數量

申請記憶體的原則:

    1、如果需要使用的記憶體小於剩餘記憶體,直接分配

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);
}

    2、 如果大於剩餘記憶體並大於1/4 的blocksize,直接分配一塊block,上一塊block中剩餘的仍可以使用(即alloc_ptr_所指向的地址仍為上一塊未使用完的block中剩餘的首地址)

    3、如果大於剩餘記憶體並小於等於1/4的blocksize,分配一塊新的block,上一塊block中剩餘的不使用(上一塊block中剩餘的記憶體小於1/4的blocksize,直接浪費了)

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.
    // 如果大於1/4 的blocksize,直接分配一塊block
    // 上一塊block中剩餘的仍可以使用
    char* result = AllocateNewBlock(bytes);
    return result;
  }

  // We waste the remaining space in the current block.
  // 如果小於等於1/4的blocksize,分配一塊新的block
  // 上一塊block中剩餘的不使用(直接浪費浪費了)
  alloc_ptr_ = AllocateNewBlock(kBlockSize);
  alloc_bytes_remaining_ = kBlockSize;

  char* result = alloc_ptr_;
  alloc_ptr_ += bytes;
  alloc_bytes_remaining_ -= bytes;
  return result;
}