0%

15-445 Project 1 - Buffer Pool Manager

Task #1 - LRU-K Replacement Policy

实现一个LRU-K替换算法,如果用堆的话,在RecordAccess时需要先删除在插入$O(logn)$,所以先直接用$O(n)$暴力

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).

说明中当多个frame最后一次有+inf时,evict掉最早访问时间最早的(不是最近一次访问)

Task #2 - Buffer Pool Manager

  • NewPage(page_id_t* page_id)如果page在buffer中,直接返回该page。如果不在buffer中,分配一个AllocatePage()
  • FetchPage(page_id_t page_id) 如果该page已经存在buffer中,那么应该增加引用计数并且记录访问,如果不在buffer中那么分配一个并执行相同操作(我一开始理解成了如果在buffer中直接返回)
  • UnpinPage(page_id_t page_id, bool is_dirty)减少对应page的引用计数,设定is dirty
  • FlushPage(page_id_t page_id) FlushAllPages() Flush对应的Page
  • DeletePage(page_id_t page_id)在buffer中删除对应的page,归还给freelist

Task #3 - Read/Write Page Guards

类似于std::lock_guard,对page实现一个RAII的封装
实现对应的拷贝构造/赋值,析构函数
还有ReadPageGuardWritePageGuard,调用对应的Latch就好concurrency - What is the difference between a lock and a latch in the context of concurrent access to a database? - Stack Overflow

Leaderboard

先记录下可能的思路,后续做完Project再来搞

  1. Buffer Manager一把大锁,没法做到并行的从磁盘读取,恰好读取/写入的时候延迟比较高,可以考虑每个frame(buffer slot)有单独的锁,在disk_manager read/write时放掉大锁(注意下不能先放掉大锁,会有race)
  2. (By ChatGPT)优先替换扫描线程访问的页面:由于 get 线程的工作负载是倾斜的,你可能希望在缓冲区管理器中保留那些更频繁地被访问的页面。因此,当需要替换页面时,你可以首先考虑那些由扫描线程访问的页面。——在LRUKNode中记录访问模式,第一遍从SCAN的Node中做LRU,找不到再去Get的Node中找
  3. LRU-K: 可以用Heap,但是替换后RecordAccess的操作就从$O(1)$变成了$O(logn)$,

Reading List