leveldb学习:内存池Arena
2015-08-21 16:13
302 查看
和SGI版的STL一样,leveldb内存分配也采用了memory pool的整理方式,减少内存不断分配释放过程中造成的空间零碎化和浪费。leveldb的内存池实现可参见arena.h和arena.cc,有关内存池的测试代码有arena_test.cc。arena内存池是leveldb的关键组件,是很多其他功能模块(class)的成员,在cache、memtable、table组件中均有使用。
先看arena的成员变量:
再看接口:
arena是按block管理内存的,当上层的组件向内存申请内存时,底层的arena将指定早已分配好的block返回给上层,当block剩余的空间不足一次申请所需的空间时,arena重新申请一个block。
leveldb向内存申请一块空间的请求交由arena实现,就会调用AllocateAligned函数,分配时要求内存对齐。
当现有的block剩余空间不足时,需要重新申请
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_大小的浪费。
先看arena的成员变量:
private: // Allocation state //当前内存池的池顶 char* alloc_ptr_; // 当前block还剩的可分配空间 size_t alloc_bytes_remaining_; // Array of new[] allocated memory blocks //每块block地址 std::vector<char*> 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<uintptr_t>(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<uintptr_t>(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_大小的浪费。
相关文章推荐
- POJ 1002 487-3279 水
- Socket通信实例二
- android 登录推断是否邮箱或手机号
- java 生成二维码 实践 图片流形式
- Eclipse 无限编译Invoking 'Maven Project Builder'导致卡主
- 线性求组合数
- Spring bean configuration inheritance
- 获取Json文件的方法
- WebSocket(1)-- WebSocket API简介
- 优先队列之左式堆
- Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast)
- 这个夏天不AC(杭州电2037)
- android cocos2dx游戏-加入截图和分享微博功能
- Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast)
- Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast)
- PL/SQL之包
- intel edison with grove lcd
- 堆(heap)和栈(stack)有什么区别??
- “错误: 找不到或无法加载主类”解决办法
- android自定义theme的使用