openGuass之shared_buffers代码走读

一.  前言

​        openGauss中的shared_buffers的配置项其实指的是共享缓冲区的大小,主要是用于配置缓冲数据块的大小。本文主要是通过走读代码了解在openGuass中shared_buffers的作用原理。

二.  shared_buffers初始化

       openGuass在初始化的时候,会将share_buffers的大小转换成block个数,因此事实上,share_buffer是通过缓存数据block进行缓存管理的。缓存的block的个数存放在g_instance.attr.attr_storage.NBuffers中,主要的初始化代码如下所示:

set_config_option
      switch (record->vartype) {
          case PGC_INT64:
              validate_conf_int
                  validate_conf_int64
                     parse_int64
                        if (flags & GUC_UNIT_MEMORY)
                           MemoryUnitConvert(&endptr, val, flags, hintmsg);
                              if (strncmp(*endptr, "kB", 2) == 0)       
                                   val /= (double)(BLCKSZ / 1024);    // 将配置的内存大小转换成BLOCKS的个数
              *conf->variable = newval    // variable指向g_instance.attr.attr_storage.NBuffers,将BLOCKS的个数存储在g_instance.attr.attr_storage.NBuffers中 
      }

        在InitBufferPool中,会根据variable指向g_instance.attr.attr_storage.NBuffers的大小尽心内存分配,如下所示:

t_thrd.storage_cxt.BufferDescriptors = ShmemInitStruct(TOTAL_BUFFER_NUM * sizeof(BufferDescPadded))
t_thrd.storage_cxt.BufferBlocks =  ShmemInitStruct("Buffer Blocks")

        后续,block相关的缓存就存放在t_thrd.storage_cxt.BufferDescriptors和t_thrd.storage_cxt.BufferBlocks中。

三.  shared_buffers没命中缓存但是缓存还没满时

​      在数据数据block的时候,刚开始总是会没命中缓存但是block还是处于空闲的状态,openGuass中的处理如下:

​      缓存相关的读取函数入口在StrategyGetBuffer中,因此开始时候,缓存总是没匹配但是空间是充足的,在get_buf_from_candidate_list的时候,直接找到一个空的buf并且返回,如下所示:

static BufferDesc* get_buf_from_candidate_list(BufferAccessStrategy strategy, uint64* buf_state)
{
    ....
    while (candidate_buf_pop(&g_instance.ckpt_cxt_ctl->pgwr_procs.writer_proc[thread_id].normal_list, &buf_id)) {
	   if (g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id]) {  //candidate_free_map为真说明对应的buf为空
	       g_instance.ckpt_cxt_ctl->candidate_free_map[buf_id] = false; // 设置为非空闲
		   AddBufferToRing(strategy, buf);   // 保存到缓存中
		   return buf;
	   }
    }
	....
}

四.  shared_buffers没命中缓存缓存已经满时

​       如果缓存已满,那么需要使用淘汰算法进行缓存置换,pg采用时钟扫描页面淘汰算法进行淘汰页面的选择,但是openGuass只是采用简单的非脏即被淘汰的算法,如下为代码流程:

BufferDesc* StrategyGetBuffer(BufferAccessStrategy strategy, uint64* buf_state)
{
    ....
    for (;;)
    {
        buf = GetBufferDescriptor(ClockSweepTick(max_buffer_can_use));
        ....
        retry_lock_status.retry_times = 0;
        // 因为BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 会一直成立,因此实际条件成了只要页面非脏,即被选中淘汰 
        if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0 && !(local_buf_state & BM_IS_META) && (backend_can_flush_dirty_page() || !(local_buf_state & BM_DIRTY))) {
            *buf_state = local_buf_state;
            return buf;
        }
    }
    ....
}

五. shared_buffers命中缓存时

     命中缓存时直接返回缓存的buf即可,代码如下所示:

BufferDesc* StrategyGetBuffer(BufferAccessStrategy strategy, uint64* buf_state)
{
    ....
    if (strategy != NULL) {
        buf = GetBufferFromRing(strategy, buf_state);
        if (buf != NULL) {
            return buf;
        }
    }
    .....
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值