日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

放大缩小保证div对齐_NFS Write IO 不对齐深度分析

發布時間:2025/3/11 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 放大缩小保证div对齐_NFS Write IO 不对齐深度分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導讀:NFSClient 對大多數的應用寫入沒有做對齊優化,本文根據 IO 不對齊的原因給出了若干實踐建議。

作者 | 裴曉輝

背景

最近團隊小伙伴弗曼統計了線上用戶數據寫入對齊情況,通過統計數據發現了一個有趣的現象: 用戶寫入請求中近 70% 的數據塊 4K 不對齊,這也就是說 NFSClient 對大多數的應用寫入沒有做對齊優化。

下面會從 NFSClient BufferWrite 實現流程的維度解釋 IO 不對齊的原因,最后據此給出了若干實踐建議。

場景分析

應用程序一般可以使用 DirectIO 或 BufferIO 兩種方式向文件寫入數據。在 DirectIO 模式時 NFSClient 直接將用戶 IO 通過 RPC 發送給服務端,因此 DirectIO 方式寫入 NFSClient 不會做對齊,但考慮到應用程序使用 DirectIO 時一般會在應用側做對齊,因此非對齊 IO 的多數應該是 BufferIO 方式。

內核使用 struct nfs_req 對象記錄某個緩存頁更改情況,同時使用 struct page 對象的 private 字段保存,因此只需分析 BufferIO 時 nfs_req 的處理邏輯就能夠知道對齊規則。NFSClient 調用 nfs_updatepage() 更新 nfs_req 對象,其核心代碼如下:

從上圖紅色框中代碼可以看出來,NFSClient 會嘗試按照緩存頁大小對 offset/count 對齊,繼續查看 nfs_can_extent_write() 函數實現:

從上述代碼可知:

1) 若為同步寫,則不嘗試對齊,這是因為對同步寫做對齊并沒有明顯收益還會放大 IO;

2) 若緩存頁內容不是最新,則不允許對齊,否則就要讀懲罰,注意 nfs_write_begin() 函數已處理是否需要讀懲罰;

3) 若持有 Write Delegation,則允許對齊,因為 Write Delegation 保證本地緩存數據一定是最新,關于 Delegation 可參考文章《NFSClient Delegation 實現與陷阱》;

4) 若不持有文件鎖,則允許對齊,注意此處依據 NFSClient 設計哲學的一個假設:應用在不持有文件鎖寫入數據時,應用側應該保證文件不會被多客戶端修改;

5) 若持有全文件的寫鎖,則允許對齊,因為寫鎖保證了本地緩存數據肯定是有效的且不存在多客戶端更改,此外這里要求全文件鎖的原因是為了簡化代碼邏輯。

合并規則

上面提到內核使用 struct nfs_req 對象表示每個緩存頁的更改情況,考慮到 struct nfs_req 只能表示單區間,因此 BufferIO 需合并同一個緩存頁的多次更改,合并規則較為簡單:

兩個寫合并后必須是一個連續的區間。

相關代碼實現可參考 nfs_try_to_update_request() 函數,代碼較為簡單,故不再詳細描述。從合并規則還可以知道:同一個緩存頁上的兩個非連續 IO 需要兩次 RPC 寫入。

緩存頁 UpdateToDate 設置

從場景分析中知道緩存頁是否設置了 UpdateToDate 標記是同一緩存頁上的兩個 IO 能否合并的重要前提條件,那 NFSClient 是什么時候將緩存頁設置為 UpdateToDate 狀態的呢?總的來說,NFSClient 在兩個地方嘗試設置該標記:

1) 將緩存頁加入到 address space 時,實現代碼是 nfs_write_begin() 函數,相關邏輯如下:

繼續查看 nfs_want_read_modify_write() 函數實現:

上圖中藍色框中是 pNFS 相關處理暫時不做討論,紅色框則是一般情況下將緩存頁加入到 address space 時是否需要讀懲罰(讀取數據后緩存頁內容自然為最新),具體的需滿足如下幾個條件:

a) 若應用打開文件模式允許讀,則允許讀懲罰,這是因為根據數據的局部性原理,剛寫入的數據很可能再次讀;

b) 緩存頁內容不是最新,若已經是最新很顯然沒必要再次讀老數據;

c) 當前緩存頁沒有正在進行的 IO,也就是說沒有向服務端有讀寫請求,注意 nfs_req 只能表示單個 IO,顯然此時不允許讀;

d) 本次修改只是緩存頁的局部內容,顯然如果全覆蓋是沒有必要讀入老數據;

2) 當內核將待修改的數據拷貝到緩存頁后會調用 nfs_write_end() 函數通知 NFSClient 數據已經拷貝到緩存頁,此時 NFSClient 需根據寫入情況設置緩存頁是否為最新的狀態:

通過上面代碼可知:

a) 藍色框中表示緩存頁是文件變大時新追加的緩存頁,此時緩存頁內容為全零,自然可設置為最新;

b) 紅色框中表示緩存頁中所有的有效數據均被覆蓋,此時緩存頁內容必然為最新;

總之,數據寫入后若完全覆蓋該緩存頁的所有原有效數據,則設置為最新。

實踐建議

至此基本搞清楚了 NFSClient BufferWrite 的對齊實現邏輯,感興趣的同學可自行編寫測試用例驗證。結合對齊實現和測試驗證,初步的可給出如下建議:

1) O_SYNC 方式不會做緩存頁對齊;

2) 當文件被大量小塊 IO 重復覆蓋寫時,可考慮用 O_RDWR 方式打開(注意副作用是會有讀懲罰),有利于聚合同一個緩存頁的寫 IO,減少 RPC 次數;

3) 使用 O_WRONLY 方式打開時,同一緩存頁的不連續更改不會做聚合,每個 IO 都會觸發一次 RPC,降低訪問性能;

4) 使用類 MPI 方式多客戶端并發修改同一文件時,條帶大小應該做到緩存頁對齊,否則可能會導致數據被錯誤覆蓋;

5) 不恰當的使用文件鎖會導致不做緩存頁對齊;

6) 不使用文件鎖時小塊 IO 可能會緩存頁對齊,導致 IO 放大。

總結

緩存頁對齊是提高 BufferIO 訪問性能地有效手段,NFSClient 在設計上盡量會嘗試緩存頁對齊,但受限于 NFS 共享特性的約束,也只能對較為有限的情況做緩存頁對齊,這就潛在地要求應用側配合才可以達到最優性能。

總結

以上是生活随笔為你收集整理的放大缩小保证div对齐_NFS Write IO 不对齐深度分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。