文章目录
系列笔记
环境配置
Project 0. C++ Primer
Project 1. Buffer Pool
Project 2. B+Tree
作业链接
作业链接
本次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)={now−lastTime(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_ptr
的unordered_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机制去管理读写保护,,,