2012-01-02 102 views
3

昨天,我問的問題在這裏:how do disable disk cache in c# invoke win32 CreateFile api with FILE_FLAG_NO_BUFFERING如何提高閱讀了大量的小文件的讀寫速度或性能

在我的性能測試顯示(讀寫測試,1000個文件,總大小220M)時,FILE_FLAG_NO_BUFFERING不能幫助我提高比.NET默認磁盤緩存性能和更低的,因爲我嘗試改變FILE_FLAG_NO_BUFFERINGFILE_FLAG_SEQUENTIAL_SCAN所能到達.net默認磁盤緩存並且速度更快。

之前,我嘗試使用MongoDB的GridFS的功能替換Windows文件系統,也不好(我不需要使用分佈式功能,只要適量)。

在我的產品中,服務器可以通過tcp/ip每秒獲得很多較小的文件(60-100k),然後將其保存到磁盤,第三個服務讀取這些文件一次(只讀一次和進程)。如果我使用異步I/O是否可以幫助我,是否可以獲得最佳速度和最佳低cpu週期?有人可以給我建議?或者我仍然可以使用FileStream類?

更新1

內存映射文件是否能實現我的demand.that所有文件寫入到一個大文件或多個並從中讀取?

+0

是否真的有必要將這些文件寫入磁盤,如果您只處理它們一次? – 2012-01-02 11:07:59

+1

只要回答你的問題,並通過檢查旁邊的「右箭頭」來幫助你完成任務,回答這個問題:-) – 2012-01-02 12:01:14

+1

@Pankaj Upadhyay,謝謝,我解決了它,我會注意到的。 – springchun 2012-01-02 12:14:38

回答

2

如果您的PC正在5-10秒寫一個100KB的文件保存到磁盤,那麼你要麼擁有世界上最古老,最慢的PC,或者你的代碼做一些非常低效的。

關閉磁盤緩存將可能使事情變得更糟而不是更好。使用磁盤緩存後,您的寫入速度會很快,而Windows稍後會將數據刷新到磁盤的速度很慢。實際上,增加I/O緩衝通常會顯着改善I/O。

你一定要使用異步寫入 - 這意味着你的服務器開始的數據寫入,然後返回響應其客戶,同時在後臺將數據寫入到磁盤的OS交易。

不應該有任何需要對寫入進行排隊(因爲如果啓用了光盤緩存,操作系統已經這樣做了),但是如果所有其他操作都失敗了,那麼可以嘗試這樣做 - 它可能有助於通過僅寫入一個文件在同一時間磁盤力求減少需要..

通常用於I/O,使用較大的緩衝區有助於提高你的吞吐量。例如,不要在循環中將每個單獨的字節寫入文件,而是在一次寫入操作中寫入緩衝區數據(理想情況下是整個文件,針對您提到的大小)。這將最小化開銷(而不是爲每個字節調用寫函數,而是爲整個文件調用一次函數)。我懷疑你可能正在做這樣的事情,因爲這是我知道將性能降低到你所建議的水平的唯一方法。

內存映射文件不會幫助你。它們非常適合訪問大文件的內容。

+0

嗨,@傑森威廉姆斯,謝謝你的建議。它讓我明白該怎麼做,謝謝。 – springchun 2012-01-02 17:39:06

1

一個buggest和顯著的改善,你的情況,就可以了,海事組織,處理FILLES 沒有它們保存到磁盤後,如果你真的需要來存儲它們,把它們在Queue和provess它另一個線程,通過將它們保存在磁盤上。通過這樣做,您將立即獲得所需的處理後數據,而不會浪費時間將數據保存到磁盤上,而且還會在磁盤上存儲文件,而不會損失file processor的計算能力。

+0

嗨,@ Tigran,之前我也考慮過使用Queue.but,客戶端在多線程中發送20-30個文件,而服務器處理一個文件需要經過5-10秒,如果很多文件保存在內存中,會拋出memoryleak異常。 – springchun 2012-01-02 12:11:55

+0

從一個地方,您可以從另一個線程加載到隊列中保存到磁盤並從隊列中刪除。不要填充所有內容並在處理完之後,而是在運行過程中進行處理。 – Tigran 2012-01-02 12:34:15