2010-04-24 53 views
1

我需要找到一種儘可能快地讀取大量小文件(大約300k文件)的方法。使用線程提高磁盤讀取性能(多個文件)

使用FileStream順序讀取它們並在一次調用中讀取整個文件需要170到208秒(您知道,重新運行時,磁盤緩存起着其作用並且時間會有所不同)。

然後我嘗試使用PInvoke與CreateFile/ReadFile和使用FILE_FLAG_SEQUENTIAL_SCAN,但我不明白任何更改。

我嘗試了幾個線程(將大集合分成大塊,並讓每個線程都讀取它的部分),這樣我就能夠提高速度(即使每個新線程達到4個也不會有5%的速度) )。

關於如何找到最有效的方法做到這一點的任何想法?

+2

假設您正在讀取常規硬盤,則使用的線程越多,物理磁盤磁頭越需要尋找不同的磁道,而不是一次只返回一個文件。因此,除了在後臺線程上執行此操作以保持應用程序在主線程上的響應外,我還是會避免使用任何多線程。另外,請看看您的硬盤規格:一旦達到最大持續吞吐量,不需要調整代碼量就可以提供幫助 - 您需要更多的硬件。 – Jono 2010-04-24 11:28:21

+0

喬諾明白了。您的硬盤受到硬件限制。獲得最大吞吐量的方法是儘量減少磁盤磁頭運動浪費的時間,因此一次只能讀取一個文件。如果您可以安排每個文件在磁盤上連續存在,應該有所幫助。 – 2010-04-24 21:17:47

回答

1

@djna已經告訴過你,你的磁盤可能一次只能服務一個線程,所以你的程序中的多個線程不會有幫助,實際上可能會讓事情變得更糟。單線程版本的代碼在執行時間上的差異似乎遠遠超過了從多線程中節省的時間。換句話說,執行時間明顯改進的統計顯着性爲0.

您可能考慮的一個選擇是轉移到專爲多線程訪問而設計的並行I/O系統。然而,這是一個很大的步驟,只有在定期進行這種操作時才適用。

另一種選擇是將文件分佈到聯網系統上的本地磁盤上,並使每個系統都通過一部分文件工作。你實施這個過程有多容易,你沒有告訴我們足夠的建議,所以想一想。

0

我的猜測是,你將會受到底層文件訪問代碼,物理磁盤活動等的限制。多線程最終可能只會顛簸磁盤。您對這些文件的創建位置有多少控制?

您可以安排他們在固態磁盤而不是物理磁盤上嗎?

您可以在數據到達時將數據加載到數據庫中。那麼你的搜索將跨越一個(可能是索引的)數據庫?

0

我會加載所有文件一次,另存爲一個大文件。然後,您的應用程序只能加載一個文件,並僅掃描300k文件,以便僅更改那些已更改(通過大小,修改日期或刪除/添加)的文件,將這些更改應用於內存中的大文件。

你說他們是小文件,所以我假設300k文件可以一次加載 - 如果不是,那麼你只需要原始300k文件的一個子集,所以大文件可以只是該子集。

這種方法不行的唯一方法是,如果別的什麼是每次運行應用程序時都寫入300k文件,那聽起來不太可能。