【CMU 15-445】Proj1 Buffer Pool Manager

本文介绍了CMU-15445项目中的三个任务:LRU-K页面替换策略、磁盘调度器实现以及BufferPoolManager的管理功能。作者分享了LRU-K算法的原理,以及如何在BufferPoolManager中实现页面操作的优化,包括页面读写、缓存管理和性能提升策略。
ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

CMU-15445汇总
本文对应的project版本为CMU-Fall-2023的project1
由于Andy要求,本博客只提供思路,不会公开任何代码

通关记录

在这里插入图片描述

在这里插入图片描述
目前的rank还比较低,lru-k后续会优化下

Task1 LRU-K Replacement Policy

LRU-KLRU一样,都属于缓冲区的页面置换算法,不同的是,LRU-K考虑的是页面的之前第K次访问时间戳与当前时间戳的差(若不足K次则优先驱逐,若有多个访问不足K次的页面,则按LRU规则驱逐),而LRU考虑的是页面最近一次访问时间戳与当前时间戳的差。一个具体的例子如下图所示,假设K=3buffer大小为3,访问序列为1 2 3 2 3 2 3 1 1 4,当访问4时,会将1驱逐掉,图中当页面访问不足K次时,时间戳为最新访问时间戳,否则为前第K次的时间戳(蓝色数字为时间戳)。
在这里插入图片描述
Task1的要求是实现src/buffer/lru_k_replacer.cpp文件中的如下几个函数:

  • Evict(frame_id_t* frame_id):使用LRU-K算法驱逐一个frame,并使用参数返回frame_id;返回值类型为bool,若驱逐成功返回true,若当前可驱逐frame数量为0,则返回false
  • RecordAccess(frame_id_t frame_id):记录给定frame的访问历史
  • Remove(frame_id_t frame_id):将给定framebuffer中移除
  • SetEvictable(frame_id_t frame_id, bool set_evictable):设置frame可驱逐不可驱逐,若设置前后该属性不一致,则需要修改类内维护的可驱逐frame数量属性
  • Size():返回当前可驱逐frame数量

个人建议的实现顺序为Size->SetEvictable->RecordAccess->Evict->Remove
主要的难点在于RecordAccessEvict中各frameLRU-K信息维护与驱逐算法实现,目前我实现的版本为暴力版本,即在RecordAccess为每个frame维护一个大小为K的访问时间戳队列;在Evict中,遍历所有可驱逐的frame,找出LRU-K timestamp最小的那个,将其驱逐。(这个做法明显太慢了,后续优化一下)

Task2 Disk Scheduler

此部分需要实现一个简单的磁盘调度器,接收BufferPoolManager发来的读写磁盘请求放入一个请求队列中;然后启动一个新线程,不断从请求队列中获取请求,根据请求类型调用对应DiskManager的读写函数进行磁盘读写。主要实现文件src/storage/disk/disk_scheduler.cpp中的两个函数:

  • Schedule(DiskRequest r):接收请求并放入请求队列
  • StartWorkerThread():线程函数,从请求队列中获取新请求,并根据请求类型调用磁盘读写函数

个人建议的实现顺序为Schedule->StartWorkerThread
不需要考虑队列的线程安全性,已经有一个Channel类帮忙实现了生产者消费者模型;关于std::promise的用法,可参考disk_scheduler_test.cpp文件。

Task3 Buffer Pool Manager

这一部分需要实现一个BufferPoolManager,结合前两部分实现的LRU-K ReplacerDisk Scheduler进行缓冲区的管理物理页的开辟、获取与释放BufferPoolManager类维护的数据结构中包含一个Page类的数组(在BufferPoolManager的构造函数中会开辟空间),数组中的每个元素即为一个一个的framePage类主要包含以下几个成员:

  • page_id_t page_id_:表示该frame指向的物理页面id
  • char* data_:用于储存对应物理页面中的真实数据
  • int pin_count_:故名思意,该framepin count,表示被多少个进程pin住,当pin_count_不为0时,该frame不能被驱逐
  • bool is_dirty_:该frame是否被写过,如果被写过则需要将内容写回磁盘

在这个任务中,我们需要实现文件src/buffer/buffer_pool_manager.cpp中的以下方法:

  • FetchPage(page_id_t page_id)
  • UnpinPage(page_id_t page_id, bool is_dirty)
  • FlushPage(page_id_t page_id)
  • NewPage(page_id_t* page_id)
  • DeletePage(page_id_t page_id)
  • FlushAllPages()

个人建议的实现顺序为:FlushPage->FlushAllPages->UnpinPage->NewPage->FetchPage->DeletePage
接下来我介绍下我每个函数的实现思路

FlushPage

功能:将给定的缓存页写回磁盘,无视is_dirty_标志
参数:page_id表示给定的想要flush到磁盘的物理页id
返回值:bool,若page_id不存在,返回false;否则true
实现:BufferPoolManager类中需要维护一个page_table_,存放着每个已分配物理页对应的frame,通过page_table_查找到给定page_id对应的frame_id,然后调用Disk Scheduler提供的scheduler方法发出写请求即可,最后清空frameis_dirty_标志。

FlushAllPages

功能:将所有有效的缓存页写回磁盘,无视is_dirty_标志
参数:无
返回值:void
实现:遍历整个buffer的所有frame,若frame上的page_id不为空,则使用与FlushPage类似方法写回磁盘即可。

UnpinPage

功能:将指定的物理页对应的framepin_count减1
参数:page_id表示给定的物理页id,is_dirty表示在pin住frame时是否发生了写操作
返回值:bool,若指定的物理页id不存在,返回false;否则true
实现:首先根据page_id找到对应的frame,将framepin_count减1,此时若pin_count为0,还需调用LRU-K Replacer提供的SetEvictable函数设置frame的状态为可驱逐。然后,根据is_dirty参数设置frameis_dirty_成员即可。

NewPage

功能:找到一个空闲frame新分配一个物理页,并将该物理页的内容读取到刚找到的这个frame
参数:page_id_t *page_id分配的物理页id以参数形式返回
返回值:Page*表示新分配的物理页最终存放的frame地址
实现:找到空闲的frame首先从一个free list里面找,如果free list为空表明现在的buffer已满,需要使用LRU-K Replacer驱逐一个frame并将其作为新物理页的承载体(若该frameis_dirty_true,那么需要先将frame中的内容写回对应的物理页)。接着,调用AllocatePage函数分配新物理页,并设置frame中的相关成员即可。最后,需要调用LRU-K Replacer提供的RecordAccess函数记录下访问历史,并调用SetEvictable函数pin住frame

FetchPage

功能:给定物理页id,获取该物理页所对应的frame
参数:page_id表示给定的物理页id
返回值:Page*表示给定物理页所在的frame地址
实现:首先从page_table_中寻找给定物理页对应的frame,若未找到,则需要驱逐缓存页,这一块的处理与NewPage函数中驱逐的处理一致,代码可以复用;若找到则进行下一步。然后,将最终确定的frame记录访问历史pin住操作,也与NewPage中的操作一致。

DeletePage

功能:给定物理页id,将物理页对应的framebuffer中删除
参数:page_id表示给定的物理页id
返回值:bool,物理页不在buffer中或删除成功则返回true;物理页存在且对应的frame仍然被pin住(pin_count不为0)时,则返回false
实现:查找物理页对应的frame,将page_idpage_table_中移除,调用LRU-K ReplacerRemove函数将frame_idbuffer中移除,并将frame_id加入free_list_中,重置frame的成员,最后调用DeallocatePage将物理页回收

Optimizations

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### CMU 15-445 Buffer Pool Implementation and Concepts #### Overview of Buffer Pools in Database Systems A buffer pool serves as a cache between the database system's memory and disk storage. This mechanism aims to reduce expensive I/O operations by keeping frequently accessed data pages in memory. The management of these pages within the buffer pool involves various strategies for eviction, replacement policies like Least Recently Used (LRU), and pinning mechanisms which prevent certain pages from being evicted. #### Key Components of Buffer Pool Management The core functionalities include page allocation, deallocation, fetching pages into the buffer when requested, writing dirty pages back to disk, ensuring consistency through logging transactions, handling concurrency control issues during multi-threaded access scenarios, and optimizing performance via prefetching techniques[^1]. #### Implementation Details Specific to Course Materials In the context of CMU’s course material specifically related to 15-445, students are expected not only to understand theoretical aspects but also gain hands-on experience implementing key features such as: - **Page Replacement Policies**: Implement different algorithms including LRU, Clock Algorithm. - **Concurrency Control Mechanisms**: Develop solutions using locks or semaphores to manage simultaneous accesses safely without causing deadlocks or race conditions. - **Logging & Recovery Protocols**: Design methods for maintaining transaction logs so that changes can be undone if necessary due to failures; implement checkpoint procedures efficiently. Below is an example code snippet demonstrating how one might start coding up parts of this functionality in C++ based on principles taught in class: ```cpp class BufferPoolManager { private: std::vector<Page*> pages_; // Array holding all managed frames/pages size_t num_pages_; public: Page* FetchPage(page_id_t page_id); }; ``` This structure allows managing multiple pages while providing functions needed for interacting with them according to specified requirements set forth throughout lectures and assignments associated with CMU 15-445 coursework.
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值