博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
levelDB源码分析-Arena
阅读量:4180 次
发布时间:2019-05-26

本文共 4539 字,大约阅读时间需要 15 分钟。

       Arena在leveldb中它是一个内存池,它所作的工作十分简单,申请内存时,将申请到的内存块放入std::vector blocks_中,在Arena的生命周期结束后,统一释放掉所有申请到的内存,内部结构如下图所示。

       Arena定义为:

class Arena {        public:        Arena();       	// 构造函数        ~Arena();		// 析构函数        // Return a pointer to a newly allocated memory block of "bytes" bytes.        char* Allocate(size_t bytes);				// 分配bytes大小的内存空间,返回分配的内存的指针        // Allocate memory with the normal alignment guarantees provided by malloc        char* AllocateAligned(size_t bytes);        // Returns an estimate of the total memory usage of data allocated        // by the arena (including space allocated but not yet used for user        // allocations).        size_t MemoryUsage() const {				// 返回已使用的内存容量(分配的内存容量+vector指针内存)            return blocks_memory_ + blocks_.capacity() * sizeof(char*);        }        private:        char* AllocateFallback(size_t bytes);        char* AllocateNewBlock(size_t block_bytes);        // Allocation state        char* alloc_ptr_;						// 每分配一个Block,记录当前可用的offset指针        size_t alloc_bytes_remaining_;				// 每分配一个Block,记录当前可用的bytes大小        // Array of new[] allocated memory blocks        std::vector
blocks_; // 每次分配的内存都放入vector中 // Bytes of memory in blocks allocated so far size_t blocks_memory_; // 当前已经分配的内存容量 // No copying allowed Arena(const Arena&); // 将拷贝构造函数及赋值构造函数设置为private,表示不运行此2个操作 void operator=(const Arena&); };
        实现如下
static const int kBlockSize = 4096;       	// 定义每个Block的大小为 4K bytes    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];        }    }    // 如果bytes超过1K,则直接调用malloc分配内存;    // 否则,重新分配一个Block,再返回bytes大小的内存    char* Arena::AllocateFallback(size_t bytes) {        if (bytes > kBlockSize / 4) {			// 当请求的内存超过 1K时,直接分配,以免造成每次Block剩余内存不能利用,产生碎片            // 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); 	// 直接分配bytes内存            return result;        }	  // 每个Block剩余的bytes不够时,产生浪费        // We waste the remaining space in the current block.        alloc_ptr_ = AllocateNewBlock(kBlockSize); 	// 分配blocksize大小的内存        alloc_bytes_remaining_ = kBlockSize;        char* result = alloc_ptr_;				        alloc_ptr_ += bytes;					// 指针偏移        alloc_bytes_remaining_ -= bytes;			// 剩余bytes大小        return result;    }    // 分配bytes大小的内存空间,返回分配的内存的指针(在头文件中,为了方便介绍,放入这里)    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_) { 			// 当前block剩余空间可用            char* result = alloc_ptr_;				// 返回当前可用内存offset指针            alloc_ptr_ += bytes;		    			// 向后偏移            alloc_bytes_remaining_ -= bytes;			// 当前剩余bytes大小            return result;        }        return AllocateFallback(bytes);    }    // 分配bytes大小的内存空间,起始地址内存对齐(void*)    char* Arena::AllocateAligned(size_t bytes) {        const int align = sizeof(void*);    // We'll align to pointer size        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; if (needed <= alloc_bytes_remaining_) { result = alloc_ptr_ + slop; alloc_ptr_ += needed; alloc_bytes_remaining_ -= needed; } else { // AllocateFallback always returned aligned memory result = AllocateFallback(bytes); } assert((reinterpret_cast
(result) & (align-1)) == 0); return result; } // 分配一个Block的内存,并放入vector中 char* Arena::AllocateNewBlock(size_t block_bytes) { char* result = new char[block_bytes]; blocks_memory_ += block_bytes; blocks_.push_back(result); return result; }
 

       从上面可以看到主要提供了两个申请函数:其中一个直接分配内存,另一个可以申请对齐的内存空间。Arena没有直接调用delete/free函数,而是在Arena的析构函数中统一释放所有的内存。

        Arena实现的是粗粒度的内存池,每个Block内都可能产生剩余部分内存不能用的问题,且不存在中间释放内存和提供内存复用机制,不适用于在全局使用,且容易造成系统内存碎片。

转载地址:http://dkwoi.baihongyu.com/

你可能感兴趣的文章
2. Add Two Numbers(链表)
查看>>
637. Average of Levels in Binary Tree(Tree)
查看>>
226. Invert Binary Tree(Tree)
查看>>
328. Odd Even Linked List(链表)
查看>>
199. Binary Tree Right Side View(Tree)
查看>>
230. Kth Smallest Element in a BST(Tree)
查看>>
求字符串的最长回文串-----Manacher's Algorithm 马拉车算法
查看>>
回溯法常用的解题模板和常见题型
查看>>
深入分析Java I/O 的工作机制
查看>>
动态规划的套路----左神
查看>>
KMP算法简解
查看>>
左神算法课进阶版总结
查看>>
左神算法基础班总结
查看>>
Linux性能优化
查看>>
进程间的通信---UNIX高级环境编程
查看>>
基于SSH开发的城市公交管理系统 JAVA MySQL
查看>>
基于SSH开发的勤工助学管理系统 JAVA MySQL
查看>>
基于SSH开发的宠物销售商城系统 JAVA MySQL
查看>>
基于springboot的宠物领养管理系统 java
查看>>
JAVA 洗衣房管理系统 宿舍洗衣机管理系统
查看>>