2009-08-20 119 views
2

我需要從3.7 GB文件讀取小數據序列。我需要讀取的位置是不是相鄰的,但我可以對IO進行排序,以便從頭到尾讀取文件。如何利用磁盤IO排隊

該文件存儲在應能夠處理/優化排隊IO的iSCSI SAN上。

問題是,如何一次性完成我需要的所有數據/職位的一次性請求?可能嗎?我不認爲異步IO是一種選擇,因爲閱讀是非常小的(20-200字節)

目前的代碼如下所示:

using (var fileStream = new FileStream(dataStorePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    for (int i = 0; i < internalIds.Count();i++) 
    { 
     fileStream.Position = seekPositions[i].SeekPosition; 
     ... = Serializer.DeserializeWithLengthPrefix<...>(fileStream, PrefixStyle.Base128); 

    } 
    ... 
} 

我在尋找各種方法來改善這個我/ O,因爲我的表現有所降低。移動頭部的所有尋求時間似乎都在增加。

回答

1

您是否在此上運行Performance Monitor(來自Microsoft Sysinternals)?

我不確定是什麼問題,但我會猜測。如果您正在從SAN讀取數據,我會認爲磁盤訪問會導致網絡請求下的問題。第一次讀取發送一個請求,讀取和緩衝數據,然後串行器構造這些對象。在發送第二個請求時,SAN磁盤繼續旋轉,因此您必須等待數據旋轉到位。

你試過多線程嗎?如果您按順序設置需要處理的文件部分的隊列,啓動一些線程,讓它們單獨打開文件(FileSharing.Read,以便它們都可以一次訪問文件)以及然後讓他們開始從隊列中抓取工作。將結果輸出到另一個集合中。如果訂單對於輸出很重要,則按輸出順序排列它們。

---編輯---

你有沒有試過ReadFileScatter APIHere's a P-invoke signature from pinvoke.net

+0

+1瞭解問題。我相信這就是發生了什麼,在第二次讀取需要完成時,磁盤已經旋轉,因此我正在尋找一種方法來執行硬件排隊。 – andreialecu 2009-08-21 08:11:09

+0

我原以爲Windows會爲你處理硬件排隊。 C#基礎上的硬盤肯定無法獲得中世紀的成就。你只能說「去這裏讀X字節」。我將嘗試使用多個線程的不同訪問模式。如果2個線程讀取A和B,然後讀取C和D,也許會更快;或者可能是A和M,然後是B和N. – 2009-08-25 02:54:36

+0

ReadFileScatter API聽起來很有前途。我的答案中添加了一個blurb。 – 2009-09-16 19:38:41

0

製作一個單個後臺線程作爲磁盤代理。將所有讀取操作發送給它,並對其進行排序併合並讀取。如果兩個或兩個以上區域接近,則讀取包含它們的完整扇區並記錄數據的子部分。異步返回數據。

+0

這些讀取已經排序,並且FileStream本身已經在默認情況下執行了這種緩衝 - 理由是爲什麼性能不是完全可怕的。請參閱以下鏈接以確認緩衝是否確實發生:http://blogs.msdn.com/brada/archive/2004/04/15/114329.aspx – andreialecu 2009-08-20 23:27:00

0

只是爲了記錄:

在POSIX環境中,您可以使用readv功能請求文件的多個區域有一個(SYS-)調用。 POSIX環境中的另一個選項是非阻塞IO。