
Linux 創始人 Linus Torvalds 在其核心儲存庫的 noref-filemap-read-with-llm 分支上,提交了一個八件式的記憶體管理改進系列,主題為「從頁面快取讀取時不使用 folio 參考」(mm: read from the page cache without folio references)。他在提交訊息中明確披露,程式碼、測試程式、審核以及提交訊息的初稿,都是在一個 LLM 程式助理(Claude Code)協助下、由他指導完成的,測試數據更是在其本人機器上跑出。[1][2]
問題:小量讀取令快取行成為瓶頸
Torvalds 在提交訊息中指出問題所在:多個執行緒同時對同一個頁面作小量讀取時,會在 folio 參考計數上互相爭用——filemap_get_read_batch() 取一次參考(lock cmpxchg),filemap_read() 再放開它(lock decl),因此每次讀取都會對 struct page 所在的那一行緩衝存入兩次。[1]
他提到這個問題由 Matthew 於 2024 年從一個客戶工作負載中提出。在他的本人筆記型電腦(i7-8565U,4 核 8 執行緒)上,以 8 個執行緒對同一頁面作 16 位元組的 pread() 時,請快取行毀了 load HITM 的 99.92%。[1]
架構:延遲釋放,改以 RCU 寬限期保證安全
Torvalds 提出的架構是:從頁面快取移除的 folio,本來就要等到一個 RCU 寬限期之後才回到頁面配置器。既然如此,一個由 xas_load() 在 rcu_read_lock() 下於 i_pages 找到的頁面,便可以一直持有著該頁面資料直達 rcu_read_unlock(),於是 filemap_read() 可以在關閉頁面錯誤的情況下,直接把資料複製到使用者緩衝區:不需要參考、不需要壓垮上的中斷緩衝區、不需要 seqcount、複製後不需要檢查,讀取大小也無限制。[1]
他指出,早期的嘗試(包括 Kiryl 的「快速短讀」)是在沒有參考的情況下複製到壓垮緩衝區、之後再驗證,但那些做法停步於驗證無法偵測的情況:頁面被釋放、重用並在同一個索引重新插入;遷移(他引用 Hugh 指 __folio_migrate_mapping() 沒有使用 page_cache_delete());以及 secretmem(Pedro)、未被接受的記憶體(Kiryl),還有「更極端的是帶有不希望出現的讀取副作用的 MMIO」(David)。他認為,延遲釋放可以消除這些情況,而非試圖測量它們。[1]
他又提到,這個做法似乎被多次建議但未真正嘗試,原因之一是 Matthew 早前反對,認為「讓這麼多記憶體管理員等待重用實在太危險」。[1]
八件式修訂系列
提交訊息列出這個系列的八個修訂:[1]
- 只在一個 RCU 寬限期之後釋放
PG_rcu_freefolios - 只在一個 RCU 寬限期之後釋放從頁面快取移除的 folios
- 不延遲正在被逐出之 inode 的頁面快取 folios 的釋放
- splice:不要鎖取頁面快取 folios
- mm/filemap:不使用 folio 參考從頁面快取讀取
- 統計有多少頁面的釋放需要等待 RCU 寬限期
- 當某個 CPU 有大量延遲釋放時,加速寬限期
- 在頁面快取移除迴圈中為加速邏輯的工作讓路
系列基於 7.3-rc6 加修訂正,基準提交為 0c2669a9f4a1。[1]
尚未合併
傳媒報導指出,這個分支出現在 Torvalds 的主要儲存庫中並不尋常——他平日主要只守護 master 分支;報導指這個改動是否會在下一個 Linux 7.4 合併窗口納入,仍有待觀察。(此段媒體觀察,不作來源引用。)
參考資料
[2] Linux 核心官方儲存庫(Torvalds)— noref-filemap-read-with-llm 分支提交記錄