2011-02-10 23 views
1

EDIT 2テキストは、リフォーマッタ徐々に各反復

で減速さて、私はgist.githubで私のソースのコピーを掲載しましたし、私は私が解決できない1つの長引く問題を抱えています。

FindLine()は常に-1を返します。私は原因をifステートメントに絞り込んだが、理由を理解できない。私はsymbolとsymbolListの両方が良いデータを渡していることを知っています。

/EDIT 2

私は.csvファイルを探しますかなり単純なC#のプログラムを持って、そのファイル内のテキストを読み込み、それを再フォーマット(とにロードされたSQLクエリからのいくつかの情報が含まれてDataTable)を作成し、後で別のプログラムで使用できるように.tsvファイルに保存します。

私の問題は、ソース.csvファイルが10,000行を超えることがあり、プログラムが行を繰り返すにつれてプログラムが徐々に遅くなることです。 .csvファイルが〜500行の場合は、完了するまでに約45秒かかりますが、今回は.csvファイルが大きくなるにつれて指数関数的に悪化します。

SQLクエリは37,000以上の行を返しますが、一度しか要求されず、.csvファイルと同じ方法でソートされるため、通常、対応するデータが見つからない限り、その場合は、すべての処理を行い、適切なエラーテキストを返します。私はそれが減速の原因ではないことを99%確信しています。

ループのyとzは正確に同じ長さである必要があります。

絶対必要な場合は、初期の.csvファイルからデータをスクラブして例を投稿することができますが、本当に明白なものが欠けていると本当に思っています。

ありがとうございました!

文字列はC#で不変である、

using System; 
using System.Collections.Generic; 
using System.Data; 
using System.Data.SqlClient; 
using System.IO; 
using System.Linq; 
using System.Text; 

namespace MoxySectorFormatter 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      DataTable resultTable = new DataTable(); 
      double curLine = 1; 
      double numLines = 0; 
      string ExportPath = @"***PATH***\***OUTFILE***.tsv"; 
      string ImportPath = @"***PATH***\***INFILE***.csv"; 
      string NewText = "SECURITY\r\n"; 
      string OrigText = ""; 
      string QueryString = "SELECT DISTINCT UPPER(MP.Symbol) AS Symbol, LOWER(MP.SecType) AS SecType, MBI.Status FROM MoxySecMaster AS MP LEFT JOIN MoxyBondInfo AS MBI ON MP.Symbol = MBI.Symbol AND MP.SecType = MBI.SecType WHERE MP.SecType <> 'caus' AND MP.SecType IS NOT NULL AND MP.Symbol IS NOT NULL ORDER BY Symbol ASC;"; 
      SqlConnection MoxyConn = new SqlConnection("server=***;database=***;user id=***;password=***"); 
      SqlDataAdapter adapter = new SqlDataAdapter(QueryString, MoxyConn); 

      MoxyConn.Open(); 
      Console.Write("Importing source file from \"{0}\".", ImportPath); 
      OrigText = File.ReadAllText(ImportPath); 
      OrigText = OrigText.Substring(OrigText.IndexOf("\r\n", 0) + 2); 
      Console.WriteLine("\rImporting source file from \"{0}\". Done!", ImportPath); 
      Console.Write("Scanning source report."); 
      for (int loop = 0; loop < OrigText.Length; loop++) 
      { 
       if (OrigText[loop] == '\r') 
        numLines++; 
      } 
      Console.WriteLine("\rScanning source report. Done!"); 
      Console.Write("Downloading SecType information."); 
      resultTable = new DataTable(); 
      adapter.Fill(resultTable); 
      MoxyConn.Close(); 
      Console.WriteLine("\rDownloading SecType information. Done!"); 

      for (int lcv = 0; lcv < numLines; lcv++) 
      { 
       int foundSpot = -1; 
       int nextStart = 0; 
       Console.Write("\rGenerating new file... {0}/{1} ({2}%) ", curLine, numLines, System.Math.Round(((curLine/numLines) * 100), 2)); 
       for (int vcl = 0; vcl < resultTable.Rows.Count; vcl++) 
       { 
        if (resultTable.Rows[vcl][0].ToString() == OrigText.Substring(0, OrigText.IndexOf(",", 0)).ToUpper() && resultTable.Rows[vcl][1].ToString().Length > 0) 
        { 
         foundSpot = vcl; 
         break; 
        } 
       } 
       if (foundSpot != -1 && foundSpot < resultTable.Rows.Count) 
       { 
        NewText += resultTable.Rows[foundSpot][1].ToString(); 
        NewText += "\t"; 
        NewText += OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)); 
        NewText += "\t"; 
        nextStart = OrigText.IndexOf(",", nextStart) + 1; 
        for (int y = 0; y < 142; y++) 
         NewText += "\t"; 
        if(resultTable.Rows[foundSpot][2].ToString() == "r") 
         NewText += @"PRE/ETM"; 
        else if (OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)) == "Municipals") 
        { 
         NewText += "Muni - "; 
         nextStart = OrigText.IndexOf(",", nextStart) + 1; 
         if (OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)).Length > 0) 
          NewText += OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)); 
         else 
          NewText += "(Orphan)"; 
        } 
        else if (OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)) == "Corporates") 
        { 
         NewText += "Corporate - "; 
         nextStart = OrigText.IndexOf(",", nextStart) + 1; 
         nextStart = OrigText.IndexOf(",", nextStart) + 1; 
         if (OrigText.Substring(nextStart, (OrigText.IndexOf("\r\n", nextStart) - nextStart)).Length > 0) 
          NewText += OrigText.Substring(nextStart, (OrigText.IndexOf("\r\n", nextStart) - nextStart)); 
         else 
          NewText += "(Unknown)"; 
        } 
        else 
         NewText += OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart)); 
        for (int z = 0; z < 17; z++) 
         NewText += "\t"; 
        NewText += "\r\n"; 
        resultTable.Rows.RemoveAt(foundSpot); 
       } 
       else 
        Console.WriteLine("\r Omitting {0}: Missing Symbol or SecType.", OrigText.Substring(nextStart, (OrigText.IndexOf(",", nextStart) - nextStart))); 
       OrigText = OrigText.Substring(OrigText.IndexOf("\r\n", 0) + 2); 
       curLine++; 
      } 
      Console.Write("Exporting file to \"{0}\".", ExportPath); 
      File.WriteAllText(ExportPath, NewText); 
      Console.WriteLine("\rExporting file to \"{0}\". Done!\nPress any key to exit.", ExportPath); 
      Console.ReadLine(); 
     } 
    } 
} 
+1

私はこれをかなりシンプルなプログラムと呼んでいません。緊急のリファクタリングのために泣いているコードと呼んでいます。 –

+0

lol私は今月のようにC#を使ってきました。まさにその意味は何ですか?私は絶対に何も提案していません。これまでにhahaのことを聞いたことのないテクニックを使って最初から始めます。 – newuser

+2

特に、 'StringBuilder'を使って調べてみましょう。 –

答えて

8

代わりの連結のために+ =演算子を使用してSystem.Text.StringBuilderオブジェクトを使用し、それが追加(だ)とAppendLine方法:ここで

は私のソースですしたがって、ループで+ =を使用するたびに、メモリに新しい文字列が作成され、最終的には減速する可能性があります。

+0

builder.AppendLine( "SECURITY"); "SECURITY \ r"または "SECURITY \ r \ n"をビルダーに追加しますか? – newuser

+1

私はそれが "セキュリティ" +環境を追加すると信じています.NewLine – Matt

+0

それは単にbuilder.Append( "SECURITY \ r \ n");それが私が必要とする正確な形式だったら? – newuser

1

すべての行を出力文字列(NewText)の末尾に追加して最後に書き出す代わりに、出力ファイルに各行を書き込む必要があります。

プログラムが出力文字列の末尾に何かを追加するたびに、C#は古い文字列と追加されたテキストに十分な大きさの新しい文字列を作成し、古い文字列をコピーして新しい文字列を追加します最後まで。

1行40文字と500行を想定すると、合計文字列サイズは〜20Kになります。その時点で、20Kコピーのすべてのオーバーヘッドはプログラムの速度を落としています。

1

これはStringBuilderについて叫んでいますが、私はこれが主な原因ではないと考えています。むしろ、指数関数的なランタイムを持つコードがあります。

私が念頭に置いているのは、foundSpotを計算するコードです。私がコードを正しく読んでいれば、これはO(n^2)であり、その他はすべてO(n)です。

3つのアドバイス:

1)リファクタリング!このルーチンはWAYです。私は "foundSpotを計算するコード"を参照する必要はありません、それは名前を持つルーチンでなければなりません。ここには少なくとも4つのルーチンがあります。

2)Stringbuilder。

3)検索ルーチンをクリーンアップする必要があります。あなたはループの回りでたくさんの繰り返し計算をしていますが、何らかの理由がない限り(私はあなたが適用しているテストを理解しようとはしません)、検索パフォーマンスが良いもので終わる必要がありますに)。

+0

私は、最終的に近い行resultTable.Rows.RemoveAt(foundSpot)のように、foundSpotを割り当てるコードがゆっくりと速くなると考えました。メインループを通過するたびに可能性の数が減少します。 – newuser

+0

また、各一意の識別子(1行に1つ)ごとにクエリを作成し、メインループの各繰り返しに対してSQL DBから1行を要求する方が速いと思いますか? – newuser

1

新しいテキストのみが追加されます。だから、単にファイルストリームに書き出すだけではないのですか?また、try catchを追加することを忘れないでください。アプリが爆発すると、ファイルストリームを閉じることができます。

また、SubString呼び出しを取り除くと、2番目のループが高速になる可能性があります。何度も何度も何度もやっている理由はありません。

string txt = OrigText.Substring(0, OrigText.IndexOf(",", 0)).ToUpper() 
for (int vcl = 0; vcl < resultTable.Rows.Count; vcl++) 
{ 
    if (resultTable.Rows[vcl][0].ToString() == txt && resultTable.Rows[vcl][1].ToString().Length > 0) 
    { 
     foundSpot = vcl; 
     break; 
    } 
} 

これらタブループはばかげています。それらは本質的に毎回構築される定数文字列です。アプリの開始時に宣言されている書式設定変数に置き換えます。

string tab17 = "\t\t\t\t\t\t\t\t\t" 
string tab142 = "\t\t\t\t\t...etc." 

//bad 
for (int z = 0; z < 17; z++) 
    NewText += "\t"; 
+0

あなたが提供したコードの2つの例を実装しましたが、私は新しい問題を抱えています。あなたは私のメインポストに行った編集を確認していただけますか? – newuser

+0

https://gist.github.com/ –

+0

[link](https://gist.github.com/822727)でコードを再度投稿してください。私は実際に私が上で話していた問題を解決しました。私の唯一の長引く問題は、FindLine()関数は常に-1を返し、良いデータが渡されているということです。 – newuser