CMU 15-445/645 fall2024 p1
在服务器内按照 bustub 文档完成开发环境配置后,P1 主要实现了 Buffer Pool 的核心路径:替换器、异步磁盘调度、页面 Guard,以及 BufferPoolManager 的页面生命周期管理。和 P0 一样,public 指模板仓库远程,origin 指我自己的远程仓库,日常开发在本地仓库完成。
Git 命令
git pull public master # 拉取模板更新
git push origin main # 推送本地提交
lru_k_replacer.cpp
lru_k_replacer.cpp 实现了 LRU-K 替换器(按 backward k-distance 选择 victim):
LRUKReplacer(...)在src/buffer/lru_k_replacer.cpp:19初始化容量、k值和内部容器。Evict在src/buffer/lru_k_replacer.cpp:21选择可驱逐帧:优先处理访问次数不足k次的帧,否则比较 backward k-distance,最终移除 victim 并更新可驱逐数量。RecordAccess在src/buffer/lru_k_replacer.cpp:75记录访问时间戳,并维护每帧最近k次访问历史。SetEvictable在src/buffer/lru_k_replacer.cpp:89切换帧可驱逐状态,同步更新size。Remove在src/buffer/lru_k_replacer.cpp:112删除指定帧(要求可驱逐)。Size在src/buffer/lru_k_replacer.cpp:131返回当前可驱逐帧数量。
disk_scheduler.cpp
disk_scheduler.cpp 实现了基于后台线程的异步磁盘调度:
DiskScheduler(...)在src/storage/disk/disk_scheduler.cpp:18启动worker线程。~DiskScheduler在src/storage/disk/disk_scheduler.cpp:23发送停止信号并join,确保线程有序退出。Schedule在src/storage/disk/disk_scheduler.cpp:31将读写请求入队(请求里带promise用于完成通知)。StartWorkerThread在src/storage/disk/disk_scheduler.cpp:33循环取队列任务,调用DiskManager::ReadPage/WritePage,完成后设置promise。
page_guard.cpp
page_guard.cpp 用 RAII 管理页面 latch 与 pin/unpin,避免资源泄漏:
ReadPageGuard构造在src/storage/page/page_guard.cpp:30,接管读锁页面。- 读
Guard的移动构造/赋值在src/storage/page/page_guard.cpp:52、src/storage/page/page_guard.cpp:79,保证所有权安全转移。 ReadPageGuard::Drop在src/storage/page/page_guard.cpp:132释放锁、减少pin,并在合适时更新replacer状态。WritePageGuard构造在src/storage/page/page_guard.cpp:173,接管写锁页面。- 写
Guard的移动构造/赋值在src/storage/page/page_guard.cpp:196、src/storage/page/page_guard.cpp:223。 WritePageGuard::Drop在src/storage/page/page_guard.cpp:284做写路径释放,保证dirty/pin/replacer状态一致。
buffer_pool_manager.cpp
buffer_pool_manager.cpp 是 P1 主体,负责管理 frame/page 的完整生命周期:
FrameHeader::Reset在src/buffer/buffer_pool_manager.cpp:44重置frame元数据(包括page_id_)。ScheduleDiskWrite/Read在src/buffer/buffer_pool_manager.cpp:109、src/buffer/buffer_pool_manager.cpp:116封装异步IO与等待逻辑。FetchPage在src/buffer/buffer_pool_manager.cpp:123处理命中和缺页:命中则增加pin并记录访问;缺页则从free list/replacer选帧,必要时刷脏页,再读入目标页并更新页表。NewPage在src/buffer/buffer_pool_manager.cpp:194分配新页号并绑定frame,初始化页面与元数据。DeletePage在src/buffer/buffer_pool_manager.cpp:226删除页面:被pin时返回失败;否则移除页表/replacer 项并回收frame。CheckedWritePage / CheckedReadPage在src/buffer/buffer_pool_manager.cpp:288、src/buffer/buffer_pool_manager.cpp:320返回WritePageGuard/ReadPageGuard(失败返回std::nullopt)。FlushPage在src/buffer/buffer_pool_manager.cpp:394将单页写回磁盘并清除dirty。FlushAllPages在src/buffer/buffer_pool_manager.cpp:440批量刷盘所有缓冲页。GetPinCount在src/buffer/buffer_pool_manager.cpp:479读取页面pin次数,便于测试与调试。
生成提交包
1.打包(与这次通过的文件列表一致)
rm -f project1-submission.zip
zip project1-submission.zip
src/include/buffer/lru_k_replacer.h
src/buffer/lru_k_replacer.cpp
src/include/buffer/buffer_pool_manager.h
src/buffer/buffer_pool_manager.cpp
src/include/storage/disk/disk_scheduler.h
src/storage/disk/disk_scheduler.cpp
src/storage/page/page_guard.cpp
src/include/storage/page/page_guard.h
2.把签名文件加进 zip(首次会交互生成 GRADESCOPE.md) python3 gradescope_sign.py
3.检查提交包内容 unzip -l project1-submission.zip