2016-04-05 3 views
1

Ich muss Tausende von Dateien so schnell wie möglich zu öffnen und zu lesen.Öffnen und lesen Sie Tausende von Dateien so schnell wie möglich

Ich habe ein paar Tests auf 13 592 Dateien durchgeführt und gefunden Methode 1, etwas schneller als Methode 2 zu sein. Diese Dateien sind in der Regel zwischen 800 Byte und 4kB. Ich würde gerne wissen, ob es etwas gibt, was ich tun kann, um diesen I/O-gebundenen Prozess schneller zu machen?

Method 1: 
    Run 1: 3:05 (don't know what happened here) 
    Run 2: 1:55 
    Run 3: 2:06 
    Run 4: 2:02 
Method 2: 
    Run 1: 2:04 
    Run 2: 2:08 
    Run 3: 2:04 
    Run 4: 2:12 

Hier ist der Code:

public class FileOpenerUtil 
{ 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="fullFilePath"></param> 
    /// <returns></returns> 
    public static string ReadFileToString(string fullFilePath) 
    { 
     while (true) 
     { 
      try 
      { 
       //Methode 1 
       using (StreamReader sr = File.OpenText(fullFilePath)) 
       { 
        string fullMessage = ""; 
        string s; 
        while ((s = sr.ReadLine()) != null) 
        { 
         fullMessage += s + "\n"; 
        } 
        return RemoveCarriageReturn(fullMessage); 
       } 
       //Methode 2 
       /*using (File.Open(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
       { 
        Console.WriteLine("Output file {0} ready.", fullFilePath); 
        string[] lines = File.ReadAllLines(fullFilePath); 
        //Every new line under the previous line 
        string fullMessage = lines.Aggregate("", (current, s) => current + s + "\n"); 
        return RemoveCarriageReturn(fullMessage); 
        //ninject kernel 


       }*/ 
       //Methode 3 

      } 
      catch (FileNotFoundException ex) 
      { 
       Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
      } 
      catch (IOException ex) 
      { 
       Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
      } 
      catch (UnauthorizedAccessException ex) 
      { 
       Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
      } 
     } 

    } 

    /// <summary> 
    /// Verwijdert '\r' in een string sequence 
    /// </summary> 
    /// <param name="message">The text that has to be changed</param> 
    /// <returns>The changed text</returns> 
    private static string RemoveCarriageReturn(string message) 
    { 
     return message.Replace("\r", ""); 
    } 
} 

Die Dateien ich sind .HL7 Dateien und sehen wie folgt zu lesen:

MSH |^~ \ & | OAZIS ||| | 20150430235954 || ADT^A03 | 23669166 | P | 2.3 |||||| ASCII EVN | A03 | 20150430235954 |||| 201504302359 PID | 1 || 6001144000 || LastName^Vorname ^^^ Mevr. | Nachname^Vorname | 19600114 | F ||| GStreetName Nummer ^^ Ort ^^ PostalCo de^B^H || 09/3444556 ^^ PH ~ 0476519246echtg ^^ CP || NL | M || 28783409 ^^^^ VN | 0000000000 | 60011402843 |||||| B |||| N PD1 | ||| 003847^LastName^Vorname |||||||| N ||| 0 PV1 | 1 | O | FDAG^000^053^001^0^2 | NULL || FDAG^000^053^001 | 003847^Nachname^Vorname || 006813^Nachname^Vorname | 1900 | 00 |||||| 006813^Nachname^Vorname | 0 | 28783409 ^^^^ VN | 1^20150430 | 01 ||||||| |||||||| 1 | 1 || D ||||| 201504301336 | 201504302359 OBX | 1 | CE | KIND_OF_DIS | RCM | 1^1 Op medizinisch Beratung OBX | 2 | CE | DESTINATION_DIS | RCM | 1^1 Terug naar huis

Sobald ich die Datei geöffnet habe, parse ich die Zeichenfolge mit j4jayant's HL7 parser und schließe die Datei.

+1

In Bezug auf "was ist hier passiert", ist der erste Lauf in der Regel immer langsamer als nachfolgende Läufe (wegen Jitter?). Versuchen Sie, Methode 1 und 2 zu wechseln, und Sie werden wahrscheinlich sehen, dass der erste Durchlauf von Methode 2 langsamer ist. – Corak

+0

Beginnen Sie mit dem Entfernen (oder Auskommentieren) des Aufrufs von 'Console.WriteLine' in Methode 2. Das Schreiben in die Konsole hat erhebliche Auswirkungen auf die Leistung. –

+0

'fullMessage + = s +" \ n ";' 'StringBuilder' sollte etwas schneller sein. – BWA

Antwort

2

habe ich 50.000 Dateien unterschiedlicher Größe (500 bis 1024 Byte).

Test 1: Ihre Methode 1 StreamReader sr = File.OpenText(fullFilePath); sr.ReadLine();
Sekunden: 3,4658937968113
Test 2: Ihre Methode 2 File.ReadAllLines(fullFilePath)
Sekunden: 5,5008349279222
Test 3: File.ReadAllText(fullFilePath);
Sekunden: 3,30782645637133
Test 4: BinaryReader b = new BinaryReader; b.ReadString();
Sekunden: 5,85779941381009
Test 5: Windows FileReader (https://msdn.microsoft.com/en-us/library/2d9wy99d.aspx)
Sekunden: 3,07036554759848
Test 6: StreamReader sr = File.OpenText(fullFilePath); sr.ReadToEnd();
Sekunden: 3,31464109255517
Test 7: StreamReader sr = File.OpenText(fullFilePath); sr.ReadToEnd();
Sekunden: 3,3364683664508
Test 8: StreamReader sr = File.OpenText(fullFilePath); sr.ReadLine();
Sekunden: 3,40426888695317
Test 9: Filestream + BufferedStream + Stream
Sekunden: 4,02871911079061
Test 10: Parallel.For using code File.ReadAllText(fullFilePath);
Sekunden: 0,89543632235447

Bester Test Ergebnisse sind Test 5 und Test 3 (einzelner Thread) Test 3 verwendet: File.ReadAllText(fullFilePath);
Test 5 verwendet Windows FileReader (https://msdn.microsoft.com/en-us/library/2d9wy99d.aspx)

Wenn Sie Threads verwenden Test 10 ist bei weitem das schnellste.

Beispiel:

int maxFiles = 50000; 
int j = 0; 
Parallel.For(0, maxFiles, x => 
{ 
    Util.Method1("readtext_" + j + ".txt"); // your read method 
    j++; 
}); 


Wenn RAMMap mit der Standby-Liste zu leeren:

Test 1: Ihre Methode 1 StreamReader sr = File.OpenText(fullFilePath); sr.ReadLine();
Sekunden: 15,1785750622961
Test 2 : Ihre Methode 2 File.ReadAllLines(fullFilePath)
Sekunden: 17,650864469466
Test 3: File.ReadAllText(fullFilePath);
Sekunden: 14,8985912878328
Test 4: BinaryReader b = new BinaryReader; b.ReadString();
Sekunden: 18,1603815767866
Test 5: Windows FileReader
Sekunden: 14, 5059765845334
Test 6: StreamReader sr = File.OpenText(fullFilePath); sr.ReadToEnd();
Sekunden: 14,864978 6336991
Test 7: StreamReader sr = File.OpenText(fullFilePath); sr.ReadToEnd();
Sekunden: 14,830567197641
Test 8: StreamReader sr = File.OpenText(fullFilePath); sr.ReadLine();
Sekunden: 14,9965866575751
Test 9: Filestream + + BufferedStream Streamreader
Sekunden: 15,7336450516575
Test 10: Parallel.For() using code File.ReadAllText(fullFilePath);
Sekunden: 4,11343060325 439

+1

Eine Sache zu beachten: Wenn es keine anderen Änderungen gibt und die Verwendung von mehreren Threads das Lesen von Daten beschleunigt, war das Lesen von Daten bei IO nicht überlastet. Ich würde auch versuchen, Ihren ** Test 10 ** erneut auszuführen, nachdem alle Caches gelöscht wurden: http://stackoverflow.com/questions/478340/clear-file-cache-to-repeat-performance-testing –

1

Ich habe den gesamten Code aus den Kommentaren angewendet. Methode 1 scheint immer noch die schnellste zu sein.

public class FileOpenerUtil 
{ 

/// <summary> 
/// 
/// </summary> 
/// <param name="fullFilePath"></param> 
/// <returns></returns> 
public static string ReadFileToString(string fullFilePath) 
{ 
    while (true) 
    { 
     try 
     { 
      //Method 1 
      using (StreamReader sr = File.OpenText(fullFilePath)) 
       { 
        string s; 
        StringBuilder message = new StringBuilder(); 
        while ((s = sr.ReadLine()) != null) 
        { 
         message.Append(s).Append("\n"); 
        } 
        return RemoveCarriageReturn(message.ToString()); 
       } 
      //Method 2 
      /* 
       string[] lines = File.ReadAllLines(fullFilePath); 
       string fullMessage = lines.Aggregate("", (current, s) =>          current + s + "\n"); 
       return RemoveCarriageReturn(fullMessage);*/ 

      } 
      //Method 3 
      /* 
       string s = File.ReadAllText(fullFilePath); 
       return RemoveCarriageReturn(s);*/ 
     } 
     catch (FileNotFoundException ex) 
     { 
      Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
     } 
     catch (IOException ex) 
     { 
      Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
     } 
     catch (UnauthorizedAccessException ex) 
     { 
      Console.WriteLine("Output file {0} not yet ready ({1})", fullFilePath, ex.Message); 
     } 
    } 

} 

/// <summary> 
/// Verwijdert '\r' in een string sequence 
/// </summary> 
/// <param name="message">The text that has to be changed</param> 
/// <returns>The changed text</returns> 
private static string RemoveCarriageReturn(string message) 
{ 
    return message.Replace("\r", ""); 
} 

}

Verwandte Themen