首页 > 其他分享 >CMU15445 lab1 - BUFFER POOL

CMU15445 lab1 - BUFFER POOL

时间:2022-10-01 22:01:18浏览次数:69  
标签:BUFFER list frame CMU15445 id lab1 LRU Page page


本文为本人完成15445 2020fall(B+树版本)时的一些记录,仅作为备忘录使用。


TASK #1 - LRU REPLACEMENT POLICY

本任务为实现一个LRU页面置换策略,建立一个关于面向磁盘的数据库的基本的概念是很重要的,如下图:

截屏2022-10-01 20.45.06

从中可以看出,实际数据是持久化存储于磁盘之上的,执行引擎主要进行一些数据操作(读/写,也即对Page增删改查),而BufferPool则是介于执行引擎和磁盘之间,位于内存中,给执行引擎提供Page。由于存储器体系结构一般表现为内存容量远小于磁盘容量,因此BufferPool是无法加载整个db的所有Pages的,因此需要在合适的时机将Page写入磁盘中,LRU就决定了牺牲哪个Page(即将哪个Page写回到磁盘中),其中包含了局部性原理的思想。

在Buffer Pool中,Page是存放在frame中的,这是要注意的一个点(buffer pool就是一个能容放多个Page的vector)。

截屏2022-10-01 21.07.01

The size of the LRUReplacer is the same as buffer pool since it contains placeholders for all of the frames in the BufferPoolManager. However, not all the frames are considered as in the LRUReplacer. The LRUReplacer is initialized to have no frame in it. Then, only the newly unpinned ones will be considered in the LRUReplacer.

所要实现的接口主要是下面四个:

  • Victim(T*) : Remove the object that was accessed the least recently compared to all the elements being tracked by the Replacer, store its contents in the output parameter and return True. If the Replacer is empty return False.
  • Pin(T) : This method should be called after a page is pinned to a frame in the BufferPoolManager. It should remove the frame containing the pinned page from the LRUReplacer.
  • Unpin(T) : This method should be called when the pin_count of a page becomes 0. This method should add the frame containing the unpinned page to the LRUReplacer.
  • Size() : This method returns the number of frames that are currently in the LRUReplacer.

LRU的实现十分的简单,是经典的leetcode题,用list套一个unordered_map即可实现。

下面主要讲一下我对PinUnPin的理解:

  • Pin(T) : 将一个Page(frame)从LRU的list中剔除。即该Page(frame)被Buffer Pool所使用了,LRU不应该牺牲该页面。
  • Unpin(T) : 加入一个Page(frame)入LRU的list。即该页面Buffer Pool目前没人使用了,LRU根据策略决定该页面的去留。
  • Victim(T*) :意思很直接,LRU根据规则(最近最少使用)有选择性的牺牲一个页面(frame)。

并发的话,直接加大锁就好了。std::lock_guard是一种RAII的加锁方式,可以不用unlock(在析构的时候unlock),比较方便。给出Victim的实现方法,其他的应 Prof. Pavlo 要求就不放出来了。

bool LRUReplacer::Victim(frame_id_t *frame_id) {
  std::lock_guard<std::mutex> lock(latch_);
  if (id2iter_.empty()) {
    return false;
  }
  auto deleting_id = lru_list_.back();
  lru_list_.pop_back();
  id2iter_.erase(deleting_id);
  *frame_id = deleting_id;
  return true;
}

TASK #2 - BUFFER POOL MANAGER

第二个任务为构造一个Buffer Pool。

The BufferPoolManager is responsible for fetching database pages from the DiskManager and storing them in memory. The BufferPoolManager can also write dirty pages out to disk when it is either explicitly instructed to do so or when it needs to evict a page to make space for a new page.

实现以下几个接口:

  • FetchPageImpl(page_id)
  • NewPageImpl(page_id)
  • UnpinPageImpl(page_id, is_dirty)
  • FlushPageImpl(page_id)
  • DeletePageImpl(page_id)
  • FlushAllPagesImpl()

(其实可以先通过测试程序了解这几个接口怎么用的,然后再去实现会比较好!)

  • NewPageImpl(page_id):新建一个Page。
  • FetchPageImpl(page_id):获取一个Page。
  • UnpinPageImpl(page_id, is_dirty):解除对某个Page的使用(别的进程可能还在使用,pin_count为0的时候可以删除)
  • DeletePageImpl(page_id):删除一个Page。
  • FlushPageImpl(page_id):强制将某个Page写盘。
  • FlushAllPagesImpl():将所有Page写盘。

这个task其实本质上就是考验对下面两个点的理解,根据提示看看DiskManager 的API是比较好实现的:

  • Dirty Flag :当该flag为真时,该页被写过了,要写回磁盘。
  • Pin/Reference Counter:引用计数,当该计数为0时,将对应frame加入LRU中;当该计数不为0时,将对应frame从LRU中删除(即不参与LRU的替换)。

该task有几个坑需要注意一下:

  1. 重复UnpinPageImpl,但is_dirty标志不同。

    • 不是简单的赋值设置is_dirty标志,而是累计,即或一下。
    • page->is_dirty_ |= is_dirty;
  2. New完一个Page后,其pin_count为1,因此不要将这个Page放入LRU。

    • replacer_->Pin(fid);
  3. New完一个Page后,要立即刷盘。可能会有new完以后unpin(false)的情况,不刷盘这一页就丢失了

    • disk_manager_->WritePage(new_page->GetPageId(), new_page->GetData());
  4. 获取frame时,先从free list获取,再从lru中获取。

    • /**
       * @brief get a free page from free_list or lru_list
       *
       * @return frame_id_t frame id, -1 is error
       */
      frame_id_t BufferPoolManager::get_free_frame() {
        frame_id_t frame_id = -1;
        if (!free_list_.empty()) {
          frame_id = free_list_.front();
          free_list_.pop_front();
      
        } else {
          replacer_->Victim(&frame_id);
        }
        return frame_id;
      }
      
  5. 删除一个Page时,要保证free list和LRU中只存在一个fid,而不是两边都有。

    • replacer_->Pin(fid);
    • free_list_.emplace_back(fid);

由于是多线程的程序,可以多跑几次测试一下,通过日志排查出错的原因。

#!/usr/bin/env bash

trap 'exit 1' INT

echo "Running test $1 for $2 iters"
for i in $(seq 1 $2); do
    echo -ne "\r$i / $2"
    LOG="$i.txt"
    # Failed go test return nonzero exit codes
    $1 &> $LOG
    if [[ $? -eq 0 ]]; then
        rm $LOG
    else
        echo "Failed at iter $i, saving log at $LOG"
    fi
done

(gradescope上测试要是失败了可以直接偷测试文件,逃

若有概念不理解的可以翻翻课件

标签:BUFFER,list,frame,CMU15445,id,lab1,LRU,Page,page
From: https://www.cnblogs.com/cxl-/p/16747863.html

相关文章

  • 如何查看家客的恶意软件 Lab1-2 恶意代码分析
    Lab1-2分析Lab1.2.exe文件目录Lab1-22.是否有这个文件被加壳或混淆的任何迹象?3.有没有任何导入函数能够暗示出这个程序的功能?4.哪些基于主机或基于网络的迹象可以......
  • 八(一)、常用类之String、StringBuffer、StringBuilder
     一、String类:字符串,使用一对“”引起来;1.String声明为final不可被继承;2.实现了Seriablizable:表示字符串是支持序列化的;Compareble:可比较大小CharSequence接口:提供对多......
  • Java使用ProtoBuffer3时报错: Cannot resolve method 'isStringEmpty' in 'GeneratedM
    错误描述我的机器是MacM1,项目中使用了ProtoBuffer3。使用protoc程序,根据proto文件生成了Java代码。在编译Java项目的时候,报错:cannotresolvemethod'isstringempty'in......
  • AVFrame 拷贝到CVPixelBufferRef 的过程
    //NotusedonOSX-frameisnevercopied.staticintcopy_avframe_to_pixel_buffer(AVCodecContext*avctx,constAVFr......
  • MIT6.824 Distributed-System(Lab1)-MapReduce
    Labaddress:http://nil.csail.mit.edu/6.824/2020/labs/lab-mr.htmlpaper:MapReduce:SimplifiedDataProcessingonLargeClustersJob:Yourjobistoimplement......
  • buffer pool
    bufferpool增删查改bufferpool存储内容:包括数据页,索引,自适应索引,字典信息等 bufferpool查找: 如上图,如果是读操作,要查找的数据所在的数据页在缓冲池中时,则......
  • js ArrayBufferView & TypeArray All In One
    jsArrayBufferView&TypeArrayAllInOne//✅>1000002**64;18446744073709552000//✅>1000002**32;4294967296//❌太小了<1000002**16;65536/......
  • String 和 StringBuffer 的区别(及StringBuffer的常用方法)
    String和StringBuffer的区别(及StringBuffer的常用方法)对比StringStringBuffer对象是否可变String创建的对象是不可变的,一旦创建不可改变StringBuffer创建......
  • protocol-buffer3语言指南-02
    AnyAny消息类型可以让你使用消息作为嵌入类型而不必持有他们的.proto定义.Any把任意序列化后的消息作为bytes包含,带有一个URL,工作起来类似一个全局唯一的标识符.为......
  • Linux FrameBuffer note
    https://learnopengl.com/Advanced-OpenGL/FramebuffersLinuxFrameBuffer如何直接操作FrameBuffer一般情况下,我们不会直接操作FrameBuffer,这是非常基础的操作,通常......