设为首页 加入收藏

TOP

leveldb学习:内存池Arena
2015-11-21 01:59:44 来源: 作者: 【 】 浏览:0
Tags:leveldb 学习 内存 Arena

和SGI版的STL一样,leveldb内存分配也采用了memory pool的整理方式,减少内存不断分配释放过程中造成的空间零碎化和浪费。leveldb的内存池实现可参见arena.h和arena.cc,有关内存池的测试代码有arena_test.cc。arena内存池是leveldb的关键组件,是很多其他功能模块(class)的成员,在cache、memtable、table组件中均有使用。
先看arena的成员变量:

private:
  // Allocation state
  //当前内存池的池顶
  char* alloc_ptr_;
  // 当前block还剩的可分配空间
  size_t alloc_bytes_remaining_;
  // Array of new[] allocated memory blocks
  //每块block地址
  std::vector
   
     blocks_; // Bytes of memory in blocks allocated so far //内存池大小 size_t blocks_memory_;
   

再看接口:

arena是按block管理内存的,当上层的组件向内存申请内存时,底层的arena将指定早已分配好的block返回给上层,当block剩余的空间不足一次申请所需的空间时,arena重新申请一个block。

char* Arena::AllocateAligned(size_t bytes) { //将对齐的值设为指针大小和8的小者 const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; //验证一个数是2的指数的奇巧淫技 assert((align & (align-1)) == 0); // Pointer size should be a power of 2 //内存对齐的奇巧淫技 size_t current_mod = reinterpret_cast
    
     (alloc_ptr_) & (align-1); size_t slop = (current_mod == 0 ? 0 : align - current_mod); size_t needed = bytes + slop; char* result; //当前block剩余空间足够,直接分配,并更新alloc_bytes_remaining_ if (needed <= alloc_bytes_remaining_) { result = alloc_ptr_ + slop; alloc_ptr_ += needed; alloc_bytes_remaining_ -= needed; } else { // AllocateFallback always returned aligned memory //剩余空间不足,重新分配block result = AllocateFallback(bytes); } assert((reinterpret_cast
     
      (result) & (align-1)) == 0); return result; }
     
    

leveldb向内存申请一块空间的请求交由arena实现,就会调用AllocateAligned函数,分配时要求内存对齐。

当现有的block剩余空间不足时,需要重新申请

block(AllocateFallback) 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; }

kBlockSize=4096,如果申请的大小大于kBlockSize/4,则将申请一个bytes大小的block,否则,申请一个kBlockSize大小的block,bytes只占block的一部分,剩下的空间交由后面使用。

arena析构函数会把容器block_中指向blocks空间的指针依次delete。也就是释放了内存空间。

缺点:arena在申请的空间大于当前block所剩空间时(needed >= alloc_bytes_remaining_),侧抛弃当前block,重新申请新的一块block,这样就会造成老block的alloc_bytes_remaining_大小的浪费。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Mongodb集群之副本集 下一篇EXCEL数据导入数据库表

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: