1

私のコードは:

    int linenumber = File.ReadLines(path).Count();

ただし、1ギガ程度のサイズのファイルの場合、長い時間(約20秒)がかかります。

誰でもこの問題を解決するためのより良い方法を知っていますか?

更新 6 :

私はあなたのソリューションをテストしました:

約 870 mb サイズのファイルの場合:

方法 1: { my code time(seconds) : 13}

方法 2 : (からMarcinJuraszek & Locke) (同じ) {

time(seconds) : 12}

方法 3 : (からRichard Deeming) { time(seconds) : 19}

方法 4 : (からuser2942249) { time(seconds) : 13}

方法 5 : (from Locke) {time(seconds) : 13は同じlineBuffer = {4096 , 8192 , 16384 , 32768} }

方法 6 : (からLocke edition 2) { time(seconds) : 9 for Buffer size = 32KB, time(seconds) : 10 for Buffer size = 64KB }

私が言ったように、私のコメントでは、native code私のPCでこのファイルを開くアプリケーション()があります5 second。したがって、これはnot about h.d.d speedです。

By Compiling MSIL to Native Code、違いwas not obvious

Conclusion:この際、他の方法よりも送料Locke method 2がかかります。faster

だから私は彼の投稿を としてマークしましたAnswer。しかし、この投稿は、もしあれば開かれますfind better idea

vote up私を助けてくれる親愛なる友人に+1を与えましたto solve the problem

ご協力いただきありがとうございます。興味深いより良いアイデア。よろしくスマートマン

4

4 に答える 4

1

各行を表す文字列を作成するのに時間がかかっていると仮定すると、次のようなものが役立つかもしれません:

public static int CountLines1(string path)
{
   int lineCount = 0;
   bool skipNextLineBreak = false;
   bool startedLine = false;
   var buffer = new char[16384];
   int readChars;

   using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, buffer.Length))
   using (var reader = new StreamReader(stream, Encoding.UTF8, false, buffer.Length, false))
   {
      while ((readChars = reader.Read(buffer, 0, buffer.Length)) > 0)
      {
         for (int i = 0; i < readChars; i++)
         {
            switch (buffer[i])
            {
               case '\n':
               {
                  if (skipNextLineBreak)
                  {
                     skipNextLineBreak = false;
                  }
                  else
                  {
                     lineCount++;
                     startedLine = false;
                  }
                  break;
               }
               case '\r':
               {
                  lineCount++;
                  skipNextLineBreak = true;
                  startedLine = false;
                  break;
               }
               default:
               {
                  skipNextLineBreak = false;
                  startedLine = true;
                  break;
               }
            }
         }
      }
   }

   return startedLine ? lineCount + 1 : lineCount;
}

編集 2:
「仮定」について彼らが言うことは本当です! 文字ごとに呼び出すオーバーヘッドは、.Read()行ごとに文字列を作成しないことによる節約よりも重要です。一度に文字のブロックを読み取るようにコードを更新しても、元の方法よりも遅くなります。

于 2013-11-05T18:09:31.980 に答える
1

テストが示したように、コードの変更は速度に大きな影響を与えません。ボトルネックは、データを処理する C# コードではなく、データを読み取るディスクにあります。

このタスクの実行速度を上げたい場合は、より高速で優れたハード ドライブを購入してください。RPM が高いものか、ソリッド ステート ドライブのいずれかです。または、RAID0 の使用を検討することもできます。これにより、ディスクの読み取り速度が向上する可能性があります。

もう 1 つのオプションは、複数のハード ドライブを用意し、ファイルを分割して各ドライブに 1 つの部分を格納することです。その後、各ドライブでファイルを処理する 1 つのタスクで作業を並列化できます。(ディスクが 1 つしかない場合に作業を並列化しても何の役にも立たず、実際に問題が発生する可能性が高いことに注意してください。)

于 2013-11-05T20:16:50.030 に答える