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

看板Python作者 (DC)時間11年前 (2014/08/12 20:25), 編輯推噓10(10039)
留言49則, 4人參與, 最新討論串1/1
我想寫測試硬碟效能的程式,主要在win7 和win xp跑 希望能保證"實際"對檔案做讀取動作,完全關閉任何系統快取 我遇到的問題是開啟檔案時,如果該檔先前有過讀寫動作時 python 中利用os.open() 或open() fd.read()時,OS並不會直接打開檔案讀出來 而是在 DRAM 中快取直接拿快取資料,造成發大量的讀寫硬碟卻沒有實際動作 試過這樣沒用 with open(copying_target_path, 'rb', buffering = 0) as fd: 避掉 FILE_SHARE_WRITE 好像也沒用 高手大大救命 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.235.222.156 ※ 文章網址: http://www.ptt.cc/bbs/Python/M.1407846340.A.58C.html

08/12 20:45, , 1F
恐怕得直接用 ctypes 或者 pywin32 呼叫 CreateFileW
08/12 20:45, 1F

08/12 20:46, , 2F
搭配FILE_FLAG_WRITE_THROUGH, FILE_FLAG_NO_BUFFERING
08/12 20:46, 2F

08/12 20:47, , 3F
我剛瞧了一下 Python 2.7 的源碼,並無以上的實作釋出
08/12 20:47, 3F

08/12 20:48, , 4F
順便附上 MSDN 重要的說明片段,http://goo.gl/pc4Dlt
08/12 20:48, 4F

08/12 20:52, , 5F
08/12 20:52, 5F

08/12 20:55, , 6F
剛剛看到有一條路可以用...應該算是隱藏的後門 XD
08/12 20:55, 6F

08/12 20:55, , 7F
from _multiprocessing import win32 之後
08/12 20:55, 7F

08/12 20:56, , 8F
就可以用 win32.CreateFile(...) 的 API 來設定 flag
08/12 20:56, 8F

08/12 21:02, , 9F
可參照 Python 官網原始碼來操作 http://goo.gl/xNBXVh
08/12 21:02, 9F

08/12 21:03, , 10F
只不過上面兩個常數沒有被寫進去,得查 header file 囉
08/12 21:03, 10F

08/12 21:19, , 11F
太感謝 嗚嗚 ~~
08/12 21:19, 11F

08/12 21:54, , 12F
可以請教一下 中文路徑編碼 在 win32.CreateFile 失敗?
08/12 21:54, 12F

08/12 22:07, , 13F
真尷尬,剛剛去看了一下 DLLs\_multiprocessing.pyd
08/12 22:07, 13F

08/12 22:09, , 14F
該檔案的 Win32 PE Import Table 是寫 CreateFileA
08/12 22:09, 14F

08/12 22:10, , 15F
猜測 CPython 2.7 當初編譯時,沒有用 UNICODE 來編譯
08/12 22:10, 15F

08/12 22:10, , 16F
只能請樓主用 ctypes.windll.kernel32.CreateFileW 囉
08/12 22:10, 16F

08/12 22:23, , 17F
不然就只能用 win32.CreateFile(r'D:\中文字.txt', ...
08/12 22:23, 17F

08/12 22:24, , 18F
Non-UNICODE 版本加減用 XD 只是這樣不是很好就是
08/12 22:24, 18F

08/12 22:37, , 19F
補充如果要自己重新編譯 Python Runtime 使其支援 XD
08/12 22:37, 19F

08/12 22:38, , 20F
除了得選 UNICODE 模式,PyArg_ParseTuple 也得改一下
08/12 22:38, 20F

08/12 22:40, , 21F
但是這不是一個很正常的方式,跟官方版本一致就好
08/12 22:40, 21F

08/13 03:24, , 22F
參考一下#1F2nhxPv,我想應該可以直接把ANSI版改成UNICODE
08/13 03:24, 22F

08/13 23:11, , 23F
感謝樓上 該部會那篇是同行po的吧 XDDDD
08/13 23:11, 23F

08/13 23:12, , 24F
今天才搞dll來開file, 原來有更好的解法
08/13 23:12, 24F

08/13 23:21, , 25F
python 有內建 fd.flush 跟os.fsync 我試只對write 有效
08/13 23:21, 25F

08/13 23:23, , 26F
read 還是一直打中cache 我就改從做dll來解問題
08/13 23:23, 26F

08/13 23:25, , 27F
莫非FlushFileBuffers 跟fd.flush不同讓 #1F2nhxPv 有效?
08/13 23:25, 27F

08/13 23:43, , 28F
基本上呢該篇文章就是我第一個回應提到的,使用pywin32
08/13 23:43, 28F

08/13 23:43, , 29F
如果樓主願意安裝pywin32的話,那是一個很棒的選擇 :D
08/13 23:43, 29F

08/13 23:44, , 30F
至於 fd.flush 實作原始碼在這邊 http://goo.gl/uirMHF
08/13 23:44, 30F

08/13 23:46, , 31F
根據原始碼 file_flush 的實作,是使用 fflush 函式
08/13 23:46, 31F

08/13 23:46, , 32F
fflush 是標準 C runtime 提供的能力,而呼叫 fflush
08/13 23:46, 32F

08/13 23:47, , 33F
並不會呼叫 Win32 API 的 FlushFileBuffers
08/13 23:47, 33F

08/13 23:48, , 34F
樓主也可以用 windbg 下中斷點測試 :D 應該不會hit才是
08/13 23:48, 34F

08/13 23:51, , 35F
畢竟 fflush 跟 FlushFileBuffers 使用的目的就不同
08/13 23:51, 35F

08/13 23:51, , 36F
而在這個狀況的確得使用 FlushFileBuffers 再搭配
08/13 23:51, 36F

08/13 23:53, , 37F
我先前的推文或該文章中所提及的那兩個 flag 才是正解
08/13 23:53, 37F

08/14 00:04, , 38F
然而 os.fsync 狀況就不同了,在視窗平台上會用_commit
08/14 00:04, 38F

08/14 00:04, , 39F
_commit 會轉呼叫 FlushFileBuffers (可下斷點驗證)
08/14 00:04, 39F

08/14 00:08, , 40F
根據以上資訊 os.fsync 應該要清緩衝,也許可以再試試
08/14 00:08, 40F

08/14 00:09, , 41F
當然使用時,你的 fd 本身在建立時也得具備那兩個 flag
08/14 00:09, 41F

08/14 22:42, , 42F
樓上大大感謝 可以請教您怎麼找到實作原始碼?
08/14 22:42, 42F

08/14 23:05, , 43F
關於 fd.flush 這才是對的版本 http://goo.gl/LQ6Wel
08/14 23:05, 43F

08/14 23:05, , 44F
上面那個連結我貼成 stackless 版,儘管內容幾乎一樣
08/14 23:05, 44F

08/14 23:06, , 45F
至於怎麼樣找原始碼? 官網就有提供下載整包源碼啦 :D
08/14 23:06, 45F

08/14 23:07, , 46F
08/14 23:07, 46F

08/14 23:08, , 47F

08/14 23:11, , 48F
要看特定版號就去官網首頁抓源碼,或在SVN找對應branch
08/14 23:11, 48F

08/14 23:33, , 49F
喔~~ 感恩 我初入門python 學習了
08/14 23:33, 49F
文章代碼(AID): #1JwWV4MC (Python)
文章代碼(AID): #1JwWV4MC (Python)