OceanBase内存管理

OceanBase系统有一个全局的定长内存池,这个内存池中维护了由64KB大小的定长的内存块组成的空闲链表。

  • 如果申请的内存不超过64KB,则尝试从空闲链表中获取一个64KB的内存块返回给申请者;如果空闲链表为空,需要首先从操作系统中申请若干个大小为64KB的内存块加入到空闲链表中。释放时将64KB的内存块返回给空闲链表中以供下次使用。(有点类似于线程池的意思)

  • 如果申请的内存超过64KB,直接调用Glibc的内存分配函数,向操作系统申请用户所需大小的内存块,释放时直接调用Glibc的内存释放函数,将内存归还给操作系统。注意如果申请的是大内存的话,就需要直接和操作系统进行交互了。

namespace oceanbase
{
  namespace common
  {
    class ObIAllocator
    {
      public:
        virtual ~ObIAllocator() {};
      public:
        virtual void *alloc(const int64_t sz) = 0;
        virtual void free(void *ptr) = 0;
        //申请模块		#define UNUSED(v) ((void)(v))
        virtual void* mod_alloc(const int64_t size, const int32_t mod_id = 0){ UNUSED(size); UNUSED(mod_id); return NULL; }
        //释放模块
        virtual void mod_free(void* p, const int32_t mod_id = 0) { UNUSED(p); UNUSED(mod_id); }
        virtual void set_mod_id(int32_t mod_id) = 0;
    };
  }
}
//ObMalloc和ObTCMalloc是上面ObIAllocator的两个实现
//区别在于ObMalloc不支持线程缓存,而ObTCMalloc支持线程缓存
class ObMalloc : public ObIAllocator
    {
      public:
        ObMalloc() : mod_id_(0) {};
        explicit ObMalloc(int32_t mod_id) : mod_id_(mod_id) {};
        ~ObMalloc() {};
      public:
        void set_mod_id(int32_t mod_id) {mod_id_ = mod_id;};
        void *alloc(const int64_t sz) {return ob_malloc(sz, mod_id_);};
        void free(void *ptr) {ob_free(ptr);};
        void* mod_alloc(const int64_t size, const int32_t mod_id){ return ob_malloc(size, mod_id); }
        void mod_free(void* p, const int32_t mod_id) { return ob_free(p, mod_id); }
      private:
        int32_t mod_id_;
    };

    class ObTCMalloc : public ObIAllocator
    {
      public:
        ObTCMalloc() : mod_id_(0) {};
        ~ObTCMalloc() {};
      public:
        void set_mod_id(int32_t mod_id) {mod_id_ = mod_id;};
        void *alloc(const int64_t sz) {return ob_tc_malloc(sz, mod_id_);};
        void free(void *ptr) {ob_tc_free(ptr, mod_id_);};
      private:
        int32_t mod_id_;
    };
//上面的ob_tc_mclloc(sz,mod_id_)调用的是这个方法
ObTSIBlockAllocator::Block* ObTSIBlockAllocator::mod_alloc_block(int64_t size, const int32_t mod_id)
    {
      int err = OB_SUCCESS;
      Block* block = NULL;
      int64_t alloc_size = 0;
      if (!inited_)
      {
        err = OB_NOT_INIT;
        TBSYS_LOG(ERROR, "not inited.");
      }
      else if (size <= 0)
      {
        err = OB_INVALID_ARGUMENT;
        TBSYS_LOG(ERROR, "size[%ld] <= 0", size);
      }
      //OceanBase将block设置为三个级别,分别是normal、medium、big,取最合适的
      //如果要申请的size大于big_block_size_,就申请size大小的内存
      //还需要为每个申请的内存设置模块号
      else if (normal_block_size_ >= size)
      {
        alloc_size = normal_block_size_;
        block = normal_block_cache_.get();
      }
      else if (medium_block_size_ >= size)
      {
        alloc_size = medium_block_size_;
        block = medium_block_cache_.get();
      }
      else if (big_block_size_ >= size)
      {
        alloc_size = big_block_size_;
        block = big_block_cache_.get();
          /*
  //首先尝试从线程局部的空闲链表申请内存块,如果申请不到,再通过ObMalloc的alloc方法申请
  TSIBlockCache::Block* TSIBlockCache::get()
    {
      BlockList* block_list = NULL;
      Block* block = NULL;
      if (!inited_)
      {
        TBSYS_LOG(ERROR, "not inited");
      }
      else if (NULL == (block_list = get_block_list_head()))
      {
        TBSYS_LOG(ERROR, "get_block_list()=>NULL");
      }
      else if (NULL != (block = block_list->pop()))
      {
        // do nothing
      }
      else if (OB_SUCCESS == global_block_list_.pop(block))
      {
        // do nothing
      }
      return block;
    }
          */
      }
      else
      {
        alloc_size = size;
        //TBSYS_LOG(TRACE, "alloc big block size[%ld]", size);
      }
      if (OB_SUCCESS == err && NULL == block)
      {
        block = alloc_block(alloc_size);
        //new(p) Block(size);  此处使用了placement_new
      }
      if (NULL != block)
      {
        block->real_size_ = size;
        block->mod_ = mod_id;
        after_alloc(block);
        //更新全局内存池的大小
        g_malloc_size_stat.add(size);
        ob_mod_usage_update(alloc_size, mod_id);
        ob_mod_usage_update(alloc_size, ObModIds::OB_MOD_TC_ALLOCATED);
        //BACKTRACE(WARN, block->size_ > 65536, "block_size=%ld", block->size_);
      }
      return block;
    }

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值