首页 > 其他分享 >CMU 15445 spring - project 1 Buffer Pool实验笔记

CMU 15445 spring - project 1 Buffer Pool实验笔记

时间:2023-08-10 15:58:08浏览次数:53  
标签:15445 GetPinCount Buffer spring EXPECT auto EQ page page0

前排提醒

本项目需要在linux/mac环境下进行开发,如果是windows最好是整个linux的环境,比如云服务器、虚拟机、wsl等。

整个课程需要仔细看文档,包括bustub的readme,每篇project的描述。

整个课程需要仔细看文档,包括bustub的readme,每篇project的描述。

整个课程需要仔细看文档,包括bustub的readme,每篇project的描述。

项目大意


水平较差,只能拿到很低的分数。

本项目分为3个部分:

  1. 实现LRU-K算法
  2. 实现缓冲池管理
  3. 实现RAII思想的PageGuard

大概难度是2最难,因为需要实现的函数最多。

提醒,改了代码文件但没改测试代码文件时候,也需要指定测试目标重新生成

Task #1 - LRU-K Replacement Policy

这个任务要求实现LRU-K替换策略。

大概意思为将硬盘中的一个page(页)存入内存中形成一个frame(页)。内存中能存入的frame有限,当需要存入新的page,但frame已经满了的时候,该把哪个旧的替换下去?这就是LRU-K解决的问题。

LRU-K记录了每个frame的访问记录,将访问时间戳存储成一个数组,下标小的表示最近的访问。当需要进行替换的时候,他先检测有没有frame的访问次数是小于k的,如果有就根据FIFO进行踢出(这里注意,项目网站和代码注释不同,正确的是FIFO);如果所有的都大于等于k次,那么数组[k-1]项(数组起始下标为0)最小的被踢出(表示第前k次访问最早)。

这里的时间戳应该为逻辑时间戳,用来分清楚操作的前后即可。

RecordAccess:增加一次记录。变更current_timestamp_, cur_size_, node_store_
Evict: 踢出 evictable 且符合上面条件的 frame。注意这里不足k次的话是FIFO。
SetEvictable: 设置 frame 是否可被踢出。变更cur_size_
Remove: 删除选中的 frame。变更cur_size_
Size:返回curr_size_的值。

线程安全方面,可以简单的加个大锁,一进函数就加锁(笑

Task #2 - Buffer Pool Manager

Buffer Pool Manager 用来从硬盘中获取实际数据,并控制替换下来的frame进行写入(假如有更改)。

NewPage: 生成一个新的 page 对象,将生成的 page_id通过参数传出,需要 pin
FetchPage:获取一个 page 对象,如果Bufferpool 里没有还需要从硬盘中获取,需要 pin
UnpinPage:减少 pin 计数。如果计数为 0 则需要将此frame标记为可被踢出的。需要注意 is_dirty_ |= is_dirty
FlushPage:把 page 内容写回到磁盘上
FlushAllPages:将所有page进行FlushPage
DeletePage: 删除一个evictable的page,replacer_将其设置为Remove,page这一块metadata需要重新设置(不要free

这里最关键的就是维护pin_count_。线程安全方面依旧可以加大锁(笑

Task #3 - Read/Write Page Guards

程序员使用Page的时候可能会忘记加锁,或者加了锁忘记释放,这时候有个PageGuard把Page封装起来,自动加锁释放锁就很方便,这是RAII思想。

程序员可以通过Buffer Pool Manager里提供的 FetchPagexxx来获取对应的PageGuard。

Drop析构函数: unpin / 释放锁。注意在PageGuard的生命周期里,只能够执行一次。
移动构造函数重载移动赋值运算符: 旧的Drop(如果有),新的变成unavailable,注意不是Drop

这里卡了我2天,因为我弱智地把获取锁写到了.h里面,大家以此为鉴。结尾我放了一些测试可以参考。

结语

要写每个task时候还是要先把整体先看完,抓住理解再去动手写。实在不会可去找人交流,在cmu选这门课的同学们还经常问助教呢,不要怕交流嘛hh

image
欢迎加群152391370一起搞cmu15-445,也可以搞他课程例如6.824,6.828(6.S081),15-213等相关内容。

附:page_guard_test

// 参考https://zhuanlan.zhihu.com/p/615312257
TEST(PageGuardTest, ReadTest) {
  const std::string db_name = "test.db";
  const size_t buffer_pool_size = 5;
  const size_t k = 2;

  auto disk_manager = std::make_shared<DiskManagerUnlimitedMemory>();
  auto bpm = std::make_shared<BufferPoolManager>(buffer_pool_size, disk_manager.get(), k);

  page_id_t page_id_temp;
  auto *page0 = bpm->NewPage(&page_id_temp);

  // test ~ReadPageGuard()
  {
    auto reader_guard = bpm->FetchPageRead(page_id_temp);
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // test ReadPageGuard(ReadPageGuard &&that)
  {
    auto reader_guard = bpm->FetchPageRead(page_id_temp);
    EXPECT_EQ(2, page0->GetPinCount());
    auto reader_guard_2 = ReadPageGuard(std::move(reader_guard));
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // test ReadPageGuard::operator=(ReadPageGuard &&that)
  {
    auto reader_guard_1 = bpm->FetchPageRead(page_id_temp);
    auto reader_guard_2 = bpm->FetchPageRead(page_id_temp);
    EXPECT_EQ(3, page0->GetPinCount());
    reader_guard_1 = std::move(reader_guard_2);
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // test ReadPageGuard::Drop()
  {
    auto reader_guard_1 = bpm->FetchPageRead(page_id_temp);
    auto reader_guard_2 = bpm->FetchPageRead(page_id_temp);
    EXPECT_EQ(3, page0->GetPinCount());
    auto reader_guard_3 = std::move(reader_guard_1);
    EXPECT_EQ(3, page0->GetPinCount());
    reader_guard_1.Drop();
    EXPECT_EQ(3, page0->GetPinCount());
    reader_guard_3.Drop();
    EXPECT_EQ(2, page0->GetPinCount());
    reader_guard_3.Drop();
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // Shutdown the disk manager and remove the temporary file we created.
  disk_manager->ShutDown();
}

TEST(PageGuardTest, WriteTest) {
  const std::string db_name = "test.db";
  const size_t buffer_pool_size = 5;
  const size_t k = 2;

  auto disk_manager = std::make_shared<DiskManagerUnlimitedMemory>();
  auto bpm = std::make_shared<BufferPoolManager>(buffer_pool_size, disk_manager.get(), k);

  page_id_t page_id_temp;
  auto *page0 = bpm->NewPage(&page_id_temp);

  // test ~WritePageGuard()
  {
    auto writer_guard = bpm->FetchPageWrite(page_id_temp);
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // test WritePageGuard(ReadPageGuard &&that)
  {
    auto writer_guard = bpm->FetchPageWrite(page_id_temp);
    auto writer_guard_2 = WritePageGuard(std::move(writer_guard));
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());

  // Shutdown the disk manager and remove the temporary file we created.
  disk_manager->ShutDown();
}

// 参考https://zhuanlan.zhihu.com/p/629006919
TEST(PageGuardTest, HHTest) {
  const std::string db_name = "test.db";
  const size_t buffer_pool_size = 5;
  const size_t k = 2;

  auto disk_manager = std::make_shared<DiskManagerUnlimitedMemory>();
  auto bpm = std::make_shared<BufferPoolManager>(buffer_pool_size, disk_manager.get(), k);

  page_id_t page_id_temp = 0;
  page_id_t page_id_temp_a;
  auto *page0 = bpm->NewPage(&page_id_temp);
  auto *page1 = bpm->NewPage(&page_id_temp_a);

  auto guarded_page = BasicPageGuard(bpm.get(), page0);
  auto guarded_page_a = BasicPageGuard(bpm.get(), page1);

  // after drop, whether destructor decrements the pin_count_ ?
  {
    auto read_guard1 = bpm->FetchPageRead(page_id_temp_a);
    EXPECT_EQ(2, page1->GetPinCount());
    read_guard1.Drop();
    EXPECT_EQ(1, page1->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());
  EXPECT_EQ(1, page1->GetPinCount());
  // test the move assignment
  {
    auto read_guard1 = bpm->FetchPageRead(page_id_temp);
    auto read_guard2 = bpm->FetchPageRead(page_id_temp_a);
    EXPECT_EQ(2, page0->GetPinCount());
    EXPECT_EQ(2, page1->GetPinCount());
    read_guard2 = std::move(read_guard1);
    EXPECT_EQ(2, page0->GetPinCount());
    EXPECT_EQ(1, page1->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());
  // test the move constructor
  {
    auto read_guard1 = bpm->FetchPageRead(page_id_temp);
    auto read_guard2(std::move(read_guard1));
    auto read_guard3(std::move(read_guard2));
    EXPECT_EQ(2, page0->GetPinCount());
  }
  EXPECT_EQ(1, page0->GetPinCount());
  EXPECT_EQ(page_id_temp, page0->GetPageId());

  // repeat drop
  guarded_page.Drop();
  EXPECT_EQ(0, page0->GetPinCount());
  guarded_page.Drop();
  EXPECT_EQ(0, page0->GetPinCount());

  disk_manager->ShutDown();
}

标签:15445,GetPinCount,Buffer,spring,EXPECT,auto,EQ,page,page0
From: https://www.cnblogs.com/1v7w/p/17620338.html

相关文章

  • 嵌入式Linux ------ 一次简单的FrameBuffer驱动开发
    Linux一次简单的FrameBuffer驱动开发设施版本CPUAllwinnerF1C200slinux6.4.0-rc4显示器1.28inch16-grayscaleOLED128x128驱动ICSSD1327Orangepi5声明本驱动仓库位于:https://github.com/AllwinnerSuniv/suniv-epd/tree/main/ssd1327本驱动代......
  • Spring Boot集成Sharding JDBC分库分表
    背景近期公司购物车项目需要使用ShardingJDBC分表,特记录下。ps:未分库依赖引入<!--sharding-sphereVersion:4.1.1--><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><ver......
  • SpringCloud
    SpringCloud这个阶段该如何让学习:三层架构+MVC框架:SpringIOCAOPSpringBoot新一代的JavaEE开发标准模块化allinone模块化开发===allinone代码没变化微服务架构4个核心问题?1.服务很多,客户端怎么访问?2.这么多服务?服务之间如何通信?3.这么多......
  • 什么是Redis,如何使用Redis,SpringBoot如何集成Redis
    官网链接:Redis首先简单理解一下1、什么是redisredis是一种开源的、内存中数据结构存储,用作数据库、缓存和消息代理。redis数据结构包含五大数据类型:字符串、散列、列表、集合、带范围查询的排序集合以及三大特殊数据类型:位图、超级日志、地理空间索引。redis内置复制、Lua脚本......
  • BeanDefinition解密:构建和管理Spring Beans的基石
    本文分享自华为云社区《Spring高手之路11——BeanDefinition解密:构建和管理SpringBeans的基石》,作者:砖业洋__。BeanDefinition是Spring中一个非常重要的概念,它包含了Spring容器用于创建、配置Bean所需的所有信息。理解BeanDefinition可以帮助我们深入掌握Spring的内部工作机......
  • spring多数据源动态切换的实现原理及读写分离的应用
    简介AbstractRoutingDataSource是Spring框架中的一个抽象类,可以实现多数据源的动态切换和路由,以满足复杂的业务需求和提高系统的性能、可扩展性、灵活性。应用场景多租户支持:对于多租户的应用,根据当前租户来选择其对应的数据源,实现租户级别的隔离和数据存储。分库分表:为了提高性能......
  • Spring Boot常见企业开发场景应用、自动配置原理结构分析
     读者应具备:SpringSpringMVC服务器端开发基础Maven基础本篇主要介绍SpringBoot在企业开发中常见场景的使用、以及SpringBoot的基本原理结构。以下为本篇设计的技术应用场景:构建SpringJava程序构建JUnit测试用例构建SpringJDBCTemplate应用程序操作数据库构建Servlet、JSP程......
  • Spring cloud智慧工地源码(项目端+监管端+数据大屏+APP)
    【智慧工地PC项目端功能总览】一.项目人员管理包括:信息管理、信息采集、证件管理、考勤管理、考勤明细、工资管理、现场统计、WIFI教育、工种管理、分包商管理、班组管理、项目管理。1.信息管理:头像、姓名、性别、身份证、进场时间、分包单位、劳务工种、项目履历、是否零工、计......
  • SpringBoot3文件管理
    目录一、简介二、工程搭建1、工程结构2、依赖管理三、上传下载1、配置管理2、上传下载四、Excel文件1、Excel创建2、Excel读取3、解析监听4、导入导出五、参考源码标签:上传.下载.Excel.导入.导出;一、简介在项目中,文件管理是常见的复杂功能;首先文件的类型比较多样,处理起来比......
  • 10、Spring之AOP概述
    10.1、概念AOP(AspectOrientedProgramming)是一种设计思想,是软件设计领域中的面向切面编程AOP是面向对象编程(OOP)的一种补充和完善,OOP是纵向继承机制,AOP是横向抽取机制AOP能通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下动态地为程序添加统一的附加功能......