CMU15445 lab1 - BUFFER POOL

2023-05-16


本文为本人完成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上测试要是失败了可以直接偷测试文件,逃

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMU15445 lab1 - BUFFER POOL 的相关文章

随机推荐

  • react ant Design pro Umi 项目左上角icon不显示

    今天本地运行项目没有问题 xff0c 打包发到远端发现logo icon不显示了 然后找了找资料说 LayoutSettings 哪里logo用链接图片可以本地图片有时候会加载异常 解决方法 xff1a 找到 app tsx 加个logo
  • ZeroMQ发布-订阅模式的应用(C++)

    我使用的ZeroMQ版本是4 2 0 xff0c 应用的是其发布 订阅模式 应该知道的细节 xff1a PUB SUB套接字是慢连接 xff0c 你无法得知SUB是何时开始接收消息的 就算你先打开了SUB套接字 xff0c 后打开PUB发送
  • Ubuntu 问题记录(1)| 关于卸载以源码方式安装的库

    Ubuntu 使用源码安装 lib 后 xff0c 如果要卸载 xff0c 则在 lib build 路径下使用 sudo make uninstall 之后再用 sudo updatedb 更新一下 lib 库 xff0c 再使用 loc
  • 注意字符数组最后会自动加\0

    今天做了一道考研题 规定数组大小为200 但是我没注意到后尾需要加 0 后来果断没有A过去 很伤心 反复不断地尝试怎么都不行 后来经一位仁兄点拨 瞬间豁然 include lt iostream gt include lt cstdio g
  • 在TypeScript中使用parseInt()

    在使用angular写一些东西的时候 xff0c 需要用到parseInt 方法来将时间戳转换成时分秒 xx时 xx分 xx秒 的格式 xff0c 但是因为angular所使用的是Typescript xff0c 而 parseInt st
  • CAS6.2.x ~ 准备(1)

    前言 CAS 企业单点登录 xff0c 目前最新版本是6 2 x Apereo 的 Central Authentication Service xff0c 通常称为CAS CAS是用于web的企业多语言单点登录解决方案 xff0c 并试图
  • MySql 安装,root初始化密码设置

    MySQL下载地址 xff1a https dev mysql com downloads mysql 2 解压MySQL压缩包 将以下载的MySQL压缩包解压到自定义目录下 我的解压目录是 C mysql 8 0 12 winx64 34
  • Python游戏项目--外星人入侵(一)

    一 安装Pygame 在终端输入 xff1a pip install user pygame 二 开始游戏项目 xff08 1 xff09 创建Pygame窗口及响应用户输入 创建一个名为alien invasion py 的文件 xff0
  • SpringSecurity OAuth2 获取Token端点TokenEndpoint、Token授权TokenGranter接口 详解

    1 前言 在 授权服务器是如何实现授权的呢 xff1f 中 xff0c 我们可以了解到服务端实现授权的流程 xff0c 同时知道 xff0c 当授权端点AuthorizationEndpoint生成授权码时 xff0c 就会重定向到客户端的
  • Make文件中赋值等号的几种类型(:=,?=,=)

    今天有一位以前仅做过Android APP开发的同学突然间问我 xff0c 说Makefile中经常可以看见 xff1a 冒号等号 61 问号等号 61 和直接等号 61 这究竟有什么区别呢 xff1f 欢迎转载 xff0c 但是请注明原出
  • 支持nvidia GPU 的硬件编解码的ffmpeg编译记要

    支持nvidia GPU 的硬件编解码的ffmpeg编译记要 中间目录 xff1a out 1 x264 下载x264 stable zip unzip x264 stable zip cd x264 stable configure en
  • 软件工程学习笔记——第三周:结构化分析方法-1

    结构化分析方法的概念 结构化分析模型 结构化分析过程
  • GBK编码表

    说明 xff1a 比如第一个 34 顿号 34 的编码就是A1A2 GBK 汉字内码扩展规范 编码表 二 全国信息技术标准化技术委员会 汉字内码扩展规范 GBK Chinese Internal Code Specification 1 0
  • SSH 使用过程中,出现的问题以及解决办法

    1 ssh登陆提示 server unexpectedly closed network connection 在使用ssh登入Linux時 xff0c 卻發生了serverunexpectedly closed network conne
  • CentOS7安装vncserver

    1 关闭防火墙和selinux systemctl stop firewalld service setenforce 0 2 安装图形支持 yum groups install 34 GNOME Desktop 34 或yum group
  • Echarts tooltip加上单位并带着图例颜色

    模仿腾讯疫情地图 xff0c Y轴有个百分比 xff0c 也就是Y轴有单位 xff0c 使用JS代码如下 xff1a tooltip trigger 39 axis 39 formatter function params var relV
  • xv6调试

    窗口1作为xv6的运行窗口 make CPUS 61 1 qemu gdb 窗口2作为gdb调试窗口 gdb multiarch kernel kernel 进入gdb后执行 set confirm off set architecture
  • mit6.s081-21-Lab1/ Xv6 and Unix utilities

    sleep Implement the UNIX program sleep for xv6 your sleep should pause for a user specified number of ticks A tick is a
  • Python+scrcpy+pyminitouch实现自动化(四)——实现语音识别自动打卡机器人

    首先要去网上下载一个想要实现自动化的软件 xff0c 下载对应的apk后拖拉到虚拟器的页面即可实现自动下载 以上是对于AS打开的模拟器进行的下载安装 xff0c 由于我找不到关于x86的企业微信 xff0c 所以我就换了逍遥模拟器 xff0
  • CMU15445 lab1 - BUFFER POOL

    本文为本人完成15445 2020fall B 43 树版本 时的一些记录 xff0c 仅作为备忘录使用 TASK 1 LRU REPLACEMENT POLICY 本任务为实现一个LRU页面置换策略 xff0c 建立一个关于面向磁盘的数据