P1 - Buffer Pool Manager
Problem Description
在這個 project 中,我們需要實現一個 buffer pool manager,總共有 3 個 Task :
- LRU-K Replacement Policy : 修改
/src/buffer/lru_k_replacer.cpp
來實現 LRU-K replacement policy - Disk Scheduler : 修改
/src/storage/disk/disk_scheduler.cpp
來實現 disk scheduler - Buffer Pool Manager : 修改
/src/buffer/buffer_pool_manager.cpp
來實現 buffer pool manager
Solution
暫時沒有針對 leaderboard 做任何優化 (希望以後有時間...),如果想要進行效能優化,可以參考最下方 Reference 中的文章。
在執行測試前,需要把測試中的 DISABLED_
拿掉再執行。
LRU-K Replacement Policy
只需要全部都使用 std::scoped_lock
即可,順便針對 LRUKNode
寫一些 get function 來方便取得資料。
Evict
: 優先度是先找有 inf 的,都是 inf 就比第一次讀取的時候哪個最早,如果都沒有 inf 的話就也找第一次讀取的時候哪個最早 (this->history_.back()
)RecordAccess
: 更新history_
中的資料Remove
: 直接刪除並注意拋出錯誤SetEvictable
: 判斷現在的情況並更改狀態Size
: 直接回 傳curr_size_
cd build
make lru_k_replacer_test -j$(nproc)
./test/lru_k_replacer_test
Disk Scheduler
需要修改兩個 function :
Schedule
: 只需要將 r 丟到request_queue_
中即可StartWorkerThread
: 設計一個 while 迴圈,並將 request 依據 read / write 的情況來執行
cd build
make disk_scheduler_test -j$(nproc)
./test/disk_scheduler_test
Buffer Pool Manager
一樣也是每個 function 都使用 std::scoped_lock
鎖住,需要特別注意如果要在如 NewPage 的 function 裡面使用 FlushPage 的話,要注意不要造成 deadlock。
FetchPage
: 先判斷有沒有在 buffer pool 中,如果有的話就直接回傳,沒有的話就要用跟 NewPage 一樣的方式來找一個位置,並且將資料讀進來,特別注意修改如pin_count_
等資料UnpinPage
: 處理pin_count_
為 0 的情況以及is_dirty_
的情況FlushPage
: 將資料寫回 disk,需要特別注意鎖的問題,我的作法是寫兩個 function,一個有鎖一個沒有鎖,如果其他有鎖的 function 要呼叫的話就使用沒有鎖的 functionNewPage
: 先檢查free_list_
有沒有空間,如果有的話就直接使用,沒有的話就要從lru_k_replacer
中排除一個資料並寫入DeletePage
: 刪除資料,需要特別注意一些 metadata 的更新FlushAllPages
: 遞迴的 call 沒有鎖的FlushPage
function 即可
cd build
make buffer_pool_manager_test -j$(nproc)
./test/buffer_pool_manager_test