簡體   English   中英

如何加快FileStream的創建速度

[英]How to speed up creation of a FileStream

我的應用程序需要打開很多小文件,比如1440個文件,每個文件包含1分鍾的數據,以讀取某一天的所有數據。 每個文件只有幾個KB大。 這是一個GUI應用程序,所以我希望用戶(==我!)不必等待太長時間。

事實證明打開文件相當慢。 經過研究,大多數時間都浪費在為每個文件創建FileStream(OpenStream = new FileStream)。 示例代碼:

// stream en reader aanmaken
FileStream OpenStream;
BinaryReader bReader;

foreach (string file in files)
{
    // bestaat de file? dan inlezen en opslaan
    if (System.IO.File.Exists(file))
    {
        long Start = sw.ElapsedMilliseconds;

        // file read only openen, anders kan de applicatie crashen
        OpenStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        Tijden.Add(sw.ElapsedMilliseconds - Start);

        bReader = new BinaryReader(OpenStream);

        // alles in één keer inlezen, werkt goed en snel
        // -bijhouden of appenden nog wel mogelijk is, zonodig niet meer appenden
        blAppend &= Bestanden.Add(file, bReader.ReadBytes((int)OpenStream.Length), blAppend);

        // file sluiten
        bReader.Close();
    }
}

使用秒表計時器,我發現大多數(> 80%)的時間花在為每個文件創建FileStream上。 創建BinaryReader並實際讀取文件(Bestanden.add)幾乎沒有時間。

我對此感到困惑,無法找到加快速度的方法。 我該怎么做才能加快FileStream的創建速度?

更新問題:

  • 在Windows 7和Windows 10上都會發生這種情況
  • 文件是本地的(在SSD磁盤上)
  • 目錄中只有1440個文件
  • 奇怪的是,稍后再次讀取(相同)文件,創建FileStreams突然幾乎沒有時間。 操作系統在某處記住文件流。
  • 即使我關閉應用程序並重新啟動它,“再次”打開文件也幾乎沒有時間。 這使得很難找到性能問題。 我不得不制作很多目錄副本來反復重新創建問題。

正如您在問題的評論中提到的, FileStream通過創建對象將第一個4K讀取為緩沖區。 您可以更改此緩沖區的大小以反映更好的數據大小。 (例如,如果文件小於緩沖區,則減少)。 如果按順序讀取文件,則可以通過FileOptions為OS提供有關此內容的提示。 此外,您可以避免使用BinaryReader ,因為您完全讀取文件。

    // stream en reader aanmaken
    FileStream OpenStream;

    foreach (string file in files)
    {
        // bestaat de file? dan inlezen en opslaan
        if (System.IO.File.Exists(file))
        {
            long Start = sw.ElapsedMilliseconds;

            // file read only openen, anders kan de applicatie crashen
            OpenStream = new FileStream(
                file,
                FileMode.Open,
                FileAccess.Read,
                FileShare.ReadWrite,
                bufferSize: 2048, //2K for example 
                options: FileOptions.SequentialScan);

            Tijden.Add(sw.ElapsedMilliseconds - Start);

            var bufferLenght = (int)OpenStream.Length;
            var buffer = new byte[bufferLenght];
            OpenStream.Read(buffer, 0, bufferLenght);

            // alles in één keer inlezen, werkt goed en snel
            // -bijhouden of appenden nog wel mogelijk is, zonodig niet meer appenden
            blAppend &= Bestanden.Add(file, buffer, blAppend);
        }
    }

我不知道Bestanden對象的類型。 但是,如果此對象具有從數組中讀取的方法,則還可以為文件重用緩沖區。

    //the buffer should be bigger than the biggest file to read
    var bufferLenght = 8192;
    var buffer = new byte[bufferLenght];

    foreach (string file in files)
    {
        //skip 
        ...
        var fileLenght = (int)OpenStream.Length;
        OpenStream.Read(buffer, 0, fileLenght);

        blAppend &= Bestanden.Add(file, /*read bytes from buffer */, blAppend);

我希望它有所幫助。

免責聲明:這個答案只是一個(成熟的)推測,它是一個Windows錯誤,而不是你可以用不同的代碼修復的東西。

所以這種行為可能與這里描述的Windows錯誤有關: “24核CPU,我無法移動我的鼠標”

這些進程都是從NtGdiCloseProcess中釋放鎖。

因此,如果FileStream在操作系統中使用並保持這樣一個關鍵鎖定,那么它將等待幾個μSecs用於每個文件,這將增加數千個文件。 它可能是一個不同的鎖,但上面提到的錯誤至少增加了類似問題的可能性。

為了證明或反駁這個假設,有必要深入了解內核的內部工作原理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM