[問題] 讀檔如何避開OS cache or buffer?

作者: dctzeng (DC)   2014-08-12 20:25:38
我想寫測試硬碟效能的程式,主要在win7 和win xp跑
希望能保證"實際"對檔案做讀取動作,完全關閉任何系統快取
我遇到的問題是開啟檔案時,如果該檔先前有過讀寫動作時
python 中利用os.open() 或open() fd.read()時,OS並不會直接打開檔案讀出來
而是在 DRAM 中快取直接拿快取資料,造成發大量的讀寫硬碟卻沒有實際動作
試過這樣沒用
with open(copying_target_path, 'rb', buffering = 0) as fd:
避掉 FILE_SHARE_WRITE 好像也沒用
高手大大救命
作者: LiloHuang (十年一刻)   2014-08-12 20:45:00
恐怕得直接用 ctypes 或者 pywin32 呼叫 CreateFileW搭配FILE_FLAG_WRITE_THROUGH, FILE_FLAG_NO_BUFFERING我剛瞧了一下 Python 2.7 的源碼,並無以上的實作釋出順便附上 MSDN 重要的說明片段,http://goo.gl/pc4Dlt
作者: ckc1ark (偽物)   2014-08-12 20:52:00
作者: LiloHuang (十年一刻)   2014-08-12 20:55:00
剛剛看到有一條路可以用...應該算是隱藏的後門 XDfrom _multiprocessing import win32 之後就可以用 win32.CreateFile(...) 的 API 來設定 flag可參照 Python 官網原始碼來操作 http://goo.gl/xNBXVh只不過上面兩個常數沒有被寫進去,得查 header file 囉
作者: dctzeng (DC)   2014-08-12 21:19:00
太感謝 嗚嗚 ~~可以請教一下 中文路徑編碼 在 win32.CreateFile 失敗?
作者: LiloHuang (十年一刻)   2014-08-12 22:07:00
真尷尬,剛剛去看了一下 DLLs\_multiprocessing.pyd該檔案的 Win32 PE Import Table 是寫 CreateFileA猜測 CPython 2.7 當初編譯時,沒有用 UNICODE 來編譯只能請樓主用 ctypes.windll.kernel32.CreateFileW 囉不然就只能用 win32.CreateFile(r'D:\中文字.txt', ...Non-UNICODE 版本加減用 XD 只是這樣不是很好就是補充如果要自己重新編譯 Python Runtime 使其支援 XD除了得選 UNICODE 模式,PyArg_ParseTuple 也得改一下但是這不是一個很正常的方式,跟官方版本一致就好
作者: os653   2014-08-13 03:24:00
參考一下#1F2nhxPv,我想應該可以直接把ANSI版改成UNICODE
作者: dctzeng (DC)   2014-08-13 23:11:00
感謝樓上 該部會那篇是同行po的吧 XDDDD今天才搞dll來開file, 原來有更好的解法python 有內建 fd.flush 跟os.fsync 我試只對write 有效read 還是一直打中cache 我就改從做dll來解問題莫非FlushFileBuffers 跟fd.flush不同讓 #1F2nhxPv 有效?
作者: LiloHuang (十年一刻)   2014-08-13 23:43:00
基本上呢該篇文章就是我第一個回應提到的,使用pywin32如果樓主願意安裝pywin32的話,那是一個很棒的選擇 :D至於 fd.flush 實作原始碼在這邊 http://goo.gl/uirMHF根據原始碼 file_flush 的實作,是使用 fflush 函式fflush 是標準 C runtime 提供的能力,而呼叫 fflush並不會呼叫 Win32 API 的 FlushFileBuffers樓主也可以用 windbg 下中斷點測試 :D 應該不會hit才是畢竟 fflush 跟 FlushFileBuffers 使用的目的就不同而在這個狀況的確得使用 FlushFileBuffers 再搭配我先前的推文或該文章中所提及的那兩個 flag 才是正解然而 os.fsync 狀況就不同了,在視窗平台上會用_commit_commit 會轉呼叫 FlushFileBuffers (可下斷點驗證)根據以上資訊 os.fsync 應該要清緩衝,也許可以再試試當然使用時,你的 fd 本身在建立時也得具備那兩個 flag
作者: dctzeng (DC)   2014-08-14 22:42:00
樓上大大感謝 可以請教您怎麼找到實作原始碼?
作者: LiloHuang (十年一刻)   2014-08-14 23:05:00
關於 fd.flush 這才是對的版本 http://goo.gl/LQ6Wel上面那個連結我貼成 stackless 版,儘管內容幾乎一樣至於怎麼樣找原始碼? 官網就有提供下載整包源碼啦 :Dtrunk 在這 http://svn.python.org/projects/trunk/http://svn.python.org/projects/python/trunk/ 更正..要看特定版號就去官網首頁抓源碼,或在SVN找對應branch
作者: dctzeng (DC)   2014-08-14 23:33:00
喔~~ 感恩 我初入門python 學習了

Links booklink

Contact Us: admin [ a t ] ucptt.com