CMU15445(2023 Spring) - Project 1. Buffer Pool

文章目录

  • 系列笔记
  • 作业链接
  • Task 1 LRU-K Replacement Policy
  • Task 2 - Buffer Pool Manager
  • Task 3 - Read/Write Page Guards

系列笔记

环境配置
Project 0. C++ Primer
Project 1. Buffer Pool(ing)

作业链接

作业链接
本次project分为三个部分:LRU-k、缓冲池、读写锁,感觉跟往年的大差不差

Task 1 LRU-K Replacement Policy

LRU应该都比较熟悉,可以参照LeetCode 146,也就是当cache装满后,踢掉最早访问的那个页面(frame),但是朴素的LRU算法有很明显的缺点:一个我频繁访问的页面刚好有一小段时间没访问,导致被一个只访问过一次的页面给踢出去了,这明显是不合理的。而LRU-k则是它的变种,它意味着优先删除的是没有被访问到k次的页面,这样就可以避免上面那种情况的发生。

这里定义一个所谓的k-distance:先看原文:Backward k-distance is computed as the difference in time between current timestamp and the timestamp of kth previous access. A frame with fewer than k historical accesses is given +inf as its backward k-distance. 可以知道,首先我们根据当前时间now减去页面的最早访问时间,就可以得到页面的k-distance,其中当页面访问次数小于k时,这个值需要加上一个+inf。形式上,我们可以得到:
D ( f r a m e ) = { n o w − l a s t T i m e ( f r a m e ) cnt(frame) >= k + i n f cnt(frame) < k D(frame)= \begin{cases} now - lastTime(frame)& \text{cnt(frame) >= k}\\ +inf& \text{cnt(frame) < k} \end{cases} D(frame)={nowlastTime(frame)+infcnt(frame) >= kcnt(frame) < k
然后是删除策略,删除策略就是删除k-distance最大的那个值,+inf自然大于别的值,因此我们会优先删除访问次数小于k的页面,如果有多个访问次数小于k的页面怎么办呢?原文是这么写的:When multiple frames have +inf backward k-distance, the replacer evicts the frame with the earliest overall timestamp (i.e., the frame whose least-recent recorded access is the overall least recent access, overall, out of all frames). 也就是说,当多个页面的k-distance值为inf时,采用FIFO策略驱逐。当没有inf时,我们知道当前时间now固定,因此k-distance的大小与页面最早访问时间呈负相关,因此我们只需要删除最早访问时间最小的一个页面即可,也就是说此时删除策略退化成了LRU。当然,同时还应当注意页面的is_evictable_权限是否为true。

搞清楚了需求,就要想一下实现了,具体实现其实一般都是维护两个队列(链表),一个装访问k次以下的页面,为FIFO队列,一个装达到k次的页面,也就是LRU队列。其中FIFO队列没什么好说的,链表模拟即可,需要注意的是此处的LRU队列的实现,和上面给出Leetcode题目、也就是传统LRU、或者说LRU-1有所区别,LRU-1保证了每次更新页面后页面都必然会出现在链表的尾部,而LRU-K则需要根据最早访问时间的次序确定页面更新后的优先级。涉及到频繁排序,我们自然想到可以采用红黑树去模拟这个LRU队列,具体而言,我们需要维护一个装有Node指针的std::set。实现上,可以维护一个存储frame_id_t -> shared_ptrunordered_map以实现内存管理,而对于两个队列(不是指queue哈),则存储weak_ptr

搞清楚这些,剩下的内容就很简单了,至于线程安全,我们只需要全程加锁即可(话说应该是可以实现无锁的吧,,,不过我是懒狗,直接加大锁,也没有细粒度加锁~)

Task 2 - Buffer Pool Manager

这一部分比较简单,所谓的Buffer Pool其实就是个Page进进出出的管理器,跟着Tips走就行了,需要注意的是这里要用到前面写好的LRU-K,意味着前面实现的效率是和后面环环相扣的。。此外还要注意线程安全。

Task 3 - Read/Write Page Guards

这一个Task以前的Lab是没有的,是23Spring为了后面的B+树开发方便而新增的,整体也不难,就是利用RAII机制去管理读写保护,,,

你可能感兴趣的:(CS15445,c++,数据库)