CMU15445 2022fall project1

silly19發表於2024-03-30

cmu15445 2022fall lab1 Buffer Pool

此project實現一個buffer pool,快取住磁碟查詢的資料。

Task1

這部分需要我們實現一個可擴充套件的雜湊表,這部分的難點在於插入操作時的分裂,由於Remove不需要我們將目錄和桶收縮回去,所以它也很簡單。

先分析清楚目錄和桶的結構。

我們可以先實現簡單的部分,Find,Remove,以及對桶的Find、Remove、Insert,這幾個函式都非常簡單,檢視一下對應類的成員變數就行了,需要注意的是對桶的insert,如果滿了直接返回false即可。

然後就是Insert函式。

  1. 首先根據索引找目錄項對應的桶,插入成功直接返回,插入失敗進入下一步
  2. while迴圈判斷應該插入的桶是否滿,因為有可能分裂並重分配節點後還是滿的,需要再次分裂
  3. 如果桶的深度不等於全域性深度時,可以不需要分裂,而是增加一個目錄項,這個我們後面再說,先說分裂的步驟
    • 全域性深度加1
    • 目錄翻倍,即複製一份到目錄的後面
  4. 記錄一下之前插入桶的深度(用於後面尋找兄弟目錄),並將深度加1,再建立一個深度一樣的桶
  5. 尋找兄弟目錄(它們是指向同一個桶的目錄,他們的低位是一樣的,低位的長度就是之前記錄的深度),因為深度增加之後它們的更高的一位就會不一樣,把高一位為1的那個目錄指標指向新的桶。
  6. 之後重新分配之前插入桶中的節點,重分配的方法就是把每個值刪掉,重新插入,因為目錄項已被我們修改,所以插入之後就會得到想要的結果。
  7. 之後再嘗試插入節點,失敗的話就會到第二步,需要再次分裂
  • 我們再講一下剛剛第3步說的不需要分裂的情況,上述過程我們發現複製出來的目錄指標,每次只會重新新增一個桶,所以還有很多指標是指向同一個桶的,那門當我們插入那種桶滿時,可以不要分裂,而是隻新增一個桶即可。

  • 步驟有點複雜,我們梳理一下,插入桶->分裂/不分裂->建立新桶->重新分配目錄項->重新分配桶內節點->再次嘗試插入,基本就是這樣,處理好細節即可。

Task2

這部分需要我們實現一個LRU-K演算法的替換器,用於buffer滿時替換frame。

面試常見的LRU演算法一般使用雙連結串列+雜湊的寫法,這裡的LRU-K需要維護兩個序列,雖然也可以使用雙連結串列+雜湊,只需要在中建新增一個哨兵節點即可,效率肯定更高,但為了寫程式碼方便,我直接使用一個雜湊表來實現,建立一個FrameInfo多記錄一些資訊即可,偷個懶。

LRU-K 演算法相比 LRU 演算法的優勢在於它考慮了元素的使用頻率,從而更加精細地選擇淘汰快取中的元素。

這部分實現非常簡單。

Task3

NewPgImp

  1. 判斷是否有freelist
    • 如果有:則拿出freelist中的新的frameid
    • 如果沒有:則判斷是否可以將Pages騰出一頁
      • 如果可騰出:則判斷騰出的頁是否為髒頁
        • 如果是髒頁:則寫回資料至磁碟,置dirty為false,清空頁memory,將頁的<pageid,frameid>從雜湊表中移除,將頁的lru記錄清除
        • 如果不是髒頁:則清空頁memory,將頁的<pageid,frameid>從雜湊表中移除,將頁的lru記錄清除
      • 如果不能騰出:返回nullptr
  2. 記錄這個新頁的訪問記錄,置framei的evict位為false
  3. 分配新的頁id,將對映關係插入雜湊表
  4. 設定新頁的後設資料(pgid,pin_count,id_dirty,memory)

FetchPgImp

  1. 先尋找頁,找到了的話,設定一下replacer_的資訊,還有page的pin_count
  2. 判斷是否還有空閒頁,如果沒有,換出一個頁並刷髒,清除page_table_replacer_的記錄,進入下一步;有空閒時拿出空閒頁id進入下一步
  3. 設定新的replacer_page_table_記錄,同時呼叫disk_manager從磁碟讀出一個所需頁。

FlushPgImp, FlushAllPgsImp,UnpinPgImp

這三個比較簡單,unpin時記得當pin_count為0時設定頁狀態為Evictable。

DeletePgImp

  • pin_count >0時不能刪除
  • 髒頁記得刷髒
  • replacer_page_table_記錄刪除
  • 呼叫DeallocatePage

Summary

project1在很久之前就做完了,當時忘記寫部落格了,重新回憶並記錄一下。