2017-03-23 6 views
0

2つのファイルの文字列を連結して3番目のファイルに保存しようとしています。しかし、最初の2つのファイルのレコードがもっと多い(たとえば、100000 +レコード)場合、出力ファイルは生成に時間がかかります。私がここで間違って何をやっている...誰かがNとMはfile1とFile2の内の行の 数を表すファイルのN×Mの内の行のデカルトを行いその後ここで何が間違っているのですか...ループごとに非常に遅い

var fileA = File.ReadAllLines("File1.txt"); 
var fileB = File.ReadAllLines("File2.txt"); 

を助けてください。それぞれ ファイル1とファイル2で100と50レコードごとがあるのであれば、出力は私はあなたが何も悪いことをやっているとは思わない* 50 = 5000 100

 FileStream fs = new FileStream("OutputFile.txt", FileMode.Create); 
     // First, save the standard output. 
     TextWriter tmp = Console.Out; 
     StreamWriter sw = new StreamWriter(fs); 


     foreach (var lst in cartesian) 
     { 
      Console.WriteLine(lst); 
      Console.SetOut(sw); 
      Console.WriteLine(lst); 
      Console.SetOut(tmp); 
      Console.WriteLine(lst); 
     } 

     sw.Close(); 
+1

なぜすべてのC#バージョンにタグを付けるのですか?もしその質問が 'xx'を特別に扱うのであれば' c#-xx'を使うべきです(そのバージョンの機能など) –

+0

おそらくその速度が遅いのは、そのような多くのレコードの結合は単純に*ロット*列挙する項目? – BradleyDotNET

+0

さらに、プログラムは2つのファイルに対して100k +ラインを読み込み、結果ファイルに10G +ラインを生成します。プロセッサは通常1G命令/秒を実行できるため、少なくとも100秒かかると思います。 –

答えて

7

です。 100,000 x 100,000レコードのデカルト結合には合法的に長い時間がかかります。 LINQではなくネストされたforループで結合を実行することで、パフォーマンスが少し向上するかもしれませんが、おそらくあなたのプロセスはI/O境界です。あなたがConsole.SetOutを使用する必要はありません

注意は、あなたがswに直接WriteLineを呼び出すことができます。

foreach (var lst in cartesian) 
{ 
    Console.WriteLine(lst); 
    sw.WriteLine(lst); 
    // and if you want to do it again: Console.WriteLine(lst); 
} 
+0

ありがとうジョナサン。私はこれを試してみましょう... – Samuel

+0

@Samuelこれは何かをスピードアップしてはならないことに注意してください。あなたが必要としなかったコードだけがあります。 – BradleyDotNET

+1

'SetOut'が内部的にどのくらい仕事をしているかによっては、たとえば、何かをフラッシュする場合。 –

0

Console.WriteLine() stdoutに書き込み比較的重いです。このテストでは、最初に100000行をテキストファイルに出力します.2回目のテストではstdoutに2回書き込み、各繰り返しではSetOutを呼び出します。これはテストがstdoutに2回書き込みを行うのと少し異なりますが、1回だけではなく、繰り返しごとに2回、SetOutを呼び出します。

FileStream fs = new FileStream(@"c:\temp\OutputFile.txt", FileMode.Create); 
StreamWriter sw = new StreamWriter(fs); 
TextWriter tmp = Console.Out; // stdout since it hasn't been changed 
Console.SetOut(sw); // point to file 
var stopw = Stopwatch.StartNew(); 
for (int i = 0; i < 100000; i++) 
{    
    Console.WriteLine(i); // writes to file 
} 
sw.Dispose(); 
fs.Dispose(); 
var toFileTotalMs = stopw.Elapsed.TotalMilliseconds; 

// Reset console to write to stdout 
Console.SetOut(tmp); 
stopw.Restart(); 
for (int i = 0; i < 100000; i++) 
{ 
    Console.WriteLine(i); // writes to stdout 
    Console.SetOut(tmp); // point to stdout (every iteration) 
    Console.WriteLine(i); // writes to stdout 
} 
var toConsoleTotalMs = stopw.Elapsed.TotalMilliseconds; 

Console.WriteLine($"toFileTotalMs={toFileTotalMs}; toConsoleTotalMs={toConsoleTotalMs};"); 

Console.Read(); // leaves console window open 

出力:

toFileTotalMs = 17.7198 toConsoleTotalMs = 15964.9133

だからそれがstdoutに2 Console.WriteLine()年代を行い、それだけによりもSetOutを呼び出すために900倍の時間がかかりますファイルに書き込みます。私はちょうどファイルへの書き込みに加えてすべての反復をSetOutと呼ぶために元のforループを変更しようとしました、そしてそれは17.7msから43.8msになりました。

関連する問題