2010年2月28日 星期日

程式設計(Windows API) - 磁碟I/O的效能測試

今天花了不少時間, 把 Q9400 那台機器的 Host 及 Guest 建立起來, 也留下了部份安裝過程式的圖片, 等有空的時候再整理成安裝教學.

在這邊要談的是, 效能測試 的部份. 現在已經有不少應用軟體, 會用種種方式幫系統效能評分, 可是我們身為資訊人, 當然也要多了解一點實作的方法, 不能只看軟體跑出來的數字.

對磁碟效能, 最直覺的想法, 就是實際產生一個檔案, 然後讀取內容, 計算花費的時間就可以得到寫入的效能, 讀出的效能. 不過在 Windows 系統中, 為了加強效能, 所以大量的運用 Cache 和 Prefetch 的技巧, 所以在寫檔時, 可能檔案還在記憶體的 Cache 中, Windows 就已經回傳寫入完成給程式了, 讀取時更有可能因為剛才寫入的東西還留在 Cache 中, 跟本就沒有到檔案系統中讀取檔案, 而是直接從 Cache中傳回檔案內容. 這樣會造成檔案系統效能很好的錯覺, 或是運氣不好, 讀寫的過程中正好碰到 Cache 要將大量的資料寫回檔案系統, 造成系統效能降低的錯覺.

那麼要如何避免 Cache 的干擾, 而確實測試檔案系統的讀寫效能呢? 查了一下資料, 發現在 Windows API 中, 就有提供這樣的參數可用. 但要注意必需要能直接調用 Windows API 才能使用這些參數, 若使用程式語言內, 包裝過的 函數 去開啟檔案, 那就會用 Windows 的預設方式, 即透過 Cache 進行讀寫.

使用上其實很簡單, 只在要 Windows API 的 CreateFile 中, 設定參數值即可, CreateFile 的語法格式如下

Syntax (C++)

HANDLE WINAPI CreateFile(
  __in LPCTSTR lpFileName,
  __in DWORD dwDesiredAccess,
  __in DWORD dwShareMode,
  __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  __in DWORD dwCreationDisposition,
  __in DWORD dwFlagsAndAttributes,
  __in_opt HANDLE hTemplateFile
  );


詳細的參數請參考 MSDN 中的說明, 我要說重點是在參數 dwFlagsAndAttributes.

dwFlagsAndAttributes是 DWORD 類型參數, 每一個 Bit 代表不同的旗標(選項). 這邊主要針對 CACHE 相關的 2 個參數介紹

FILE_FLAG_WRITE_THROUGH (0x80000000) 此旗標會使任何對該控制代碼所做直接寫入檔案而不被緩衝的寫入,  但仍會寫入 Cache 中. 在設計上一般是運用在網路或外接裝置的寫出, 例如隨身碟的檔案寫入, 若未加入此參數, 在寫一個檔案到隨身碟, 不要退出硬體就直接拔出隨身碟, 你會發現剛才寫入的檔案居然不見了. 因為系統在傳回寫入成功後, 只是寫到 Cache 中, 還沒真的寫到外接裝置上.


FILE_FLAG_NO_BUFFERING (0x20000000) 此旗標是代表系統會排除所有緩衝先期讀取檔案和磁碟快取, 同時也使所有讀取都保證從 "檔案" 中取得, 不能從任何系統緩衝區或磁碟快取之中讀取. 不過有些特例, 像透過網路芳鄰讀取遠端的檔案, 系統會忽略此參數, 會先試著從 Cache 中讀取檔案內容.

這 2 個 Flag 可以分開設定, 也可以合併使用, 在設計檔案系統的讀寫效能測試時, 就可以下這 2個Flag, 先將檔案寫入到檔案系統中後, 再讀取該檔案的內容即可. 很簡單, 不是嗎?

沒有留言:

張貼留言