• leveldb 之 内存管理


    leveldb 内存管理部分主要是arena.h 和arena.cc 部分完成

    整体的内存管理策略是按照block管理。大于1/4的都按照block分配。作为一个单独的block维护。

    当小于1/4block的尽量复用剩余内存。 

    不太理解为什么不是那种直接分配大内存的方式(这样估计还是会产生很多内存空洞)。

    arena.h文件如下:

    // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file. See the AUTHORS file for names of contributors.
    
    #ifndef STORAGE_LEVELDB_UTIL_ARENA_H_
    #define STORAGE_LEVELDB_UTIL_ARENA_H_
    
    #include <cstddef>
    #include <vector>
    #include <assert.h>
    #include <stdint.h>
    
    namespace leveldb {
    
    /*
     * 内存管理的类
     */
    class Arena {
     public:
      Arena();
      ~Arena();
    
      // Return a pointer to a newly allocated memory block of "bytes" bytes.
      /*
       * 分配内存
       */
      char* Allocate(size_t 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 {
        return blocks_memory_ + blocks_.capacity() * sizeof(char*);
      }
    
     private:
      char* AllocateFallback(size_t bytes);
      char* AllocateNewBlock(size_t block_bytes);
    
      // 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_;
    
      // No copying allowed
      Arena(const Arena&);
      void operator=(const Arena&);
    };
    
    /*
     * bytes 必须大于0
     * 当bytes 小于alloc_bytes_remaining_ 时,使用alloc_bytes_remaining_
     * 否则调用AllocateFallback 分配内存。
     */
    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);
    }
    
    }  // namespace leveldb
    
    #endif  // STORAGE_LEVELDB_UTIL_ARENA_H_
    

      

    arena.cc如下

    // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file. See the AUTHORS file for names of contributors.
    
    #include "util/arena.h"
    #include <assert.h>
    
    namespace leveldb {
    
    /*
     * block 大小 4K
     */
    static const int kBlockSize = 4096;
    
    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];
      }
    }
    
    /*
     * 大于1/4 块大小的时候,分配单独块
     * 否则,分配一个快,使用邋alloc_ptr指向带分贝位置。
     * 使用alloc_bytes_remaining_ 保存剩余内存大小
     * 
     */
    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;
    }
    
    /*
     * 考虑内存对齐的内存分配。
     *  align必须为2的指数次方
     */
    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<uintptr_t>(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<uintptr_t>(result) & (align-1)) == 0);
      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;
    }
    
    }  // namespace leveldb
    

      

  • 相关阅读:
    Visual Studio各版本区别
    调试ASP.NET网站IIS环境问题解决方法汇总
    关于Webpage Not Found问题解决~~~
    SpringCloud+vue搭建的商城项目
    springcloud实现限流
    ReentrantLock
    栈和堆的特点
    你用对锁了吗?浅谈 Java “锁” 事
    ReentrantReadWriteLock读写锁的使用
    OAuth2
  • 原文地址:https://www.cnblogs.com/lovemdx/p/2537281.html
Copyright © 2020-2023  润新知