2011-02-10 3 views
1

편집과 2텍스트 포매터가 점차적으로 각 반복

좋아 느리게, 나는 gist.github에 내 소스의 사본을 게시 한 나는 단지 내가 해결할 수없는 하나의 느린 문제가 있습니다.

FindLine()은 항상 -1을 반환합니다. 원인을 if 문으로 좁혔지만 이유를 알 수 없습니다. 나는 symbol과 symbolList가 모두 좋은 데이터를 전달한다는 것을 안다.

은/EDIT 내가, .csv 파일을 찾습니다 비교적 간단한 C# 프로그램이 2

가 다시 포맷, 해당 파일의 텍스트를 읽고 (그리고에로드 SQL 쿼리에서 몇 가지 정보를 포함 DataTable)에 저장하고 나중에 다른 프로그램에서 사용할 수 있도록 .tsv 파일에 저장합니다.

내 문제는 때로는 소스 .csv 파일이 10,000 줄을 넘기 때문에 프로그램이 줄을 반복하면서 느려지는 경우가 있습니다. .csv 파일이 ~ 500 줄이면 완료하는 데 약 45 초가 걸리고이 시간은 .csv 파일이 커질수록 기하 급수적으로 악화됩니다.

SQL 쿼리는 37,000+ 회선을 반환하지만 한 번만 요청되고 .csv 파일과 동일한 방식으로 정렬되므로 일반적으로 해당 파일을 찾을 수없는 경우 해당 파일을 실행하지 않습니다. 이 경우 모든 오류를 처리하고 해당 오류 텍스트를 반환합니다. 나는 그것이 감속의 원인이 아니라는 것을 99 % 확신한다.

루프 용 y 및 z는 정확히 동일해야합니다.

필자가 초기 .csv 파일에서 일부 데이터를 제거하고 예제를 게시 할 수 있으면 정말 실용적인 것을 놓치기를 바라고 있습니다.

미리 감사드립니다. 여기

내 소스이다 :

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 방법

문자열 C에서 # 불변 따라서 루프에서 + =를 사용할 때마다 새로운 문자열이 메모리에 만들어져 결국 속도가 느려질 수 있습니다.

+0

겠습니까 builder.AppendLine ("보안"); "SECURITY \ r"또는 "SECURITY \ r \ n"을 빌더에 추가 하시겠습니까? – newuser

+1

"보안"+ 환경을 추가한다고 생각합니다 .NewLine – Matt

+0

단순히 builder.Append ("SECURITY \ r \ n"); 그게 내가 필요한 정확한 형식이라면? – newuser

1

모든 줄을 출력 문자열 (NewText)의 끝에 추가하고 끝에 쓰는 대신 출력 파일에 각 줄을 작성해야합니다.

프로그램이 출력 문자열의 끝에 뭔가를 추가 할 때마다 C#은 이전 문자열과 추가 된 텍스트에 충분히 큰 새 문자열을 만들고 대상 문자열에 이전 내용을 복사 한 다음 새 텍스트를 추가합니다 끝까지.

한 줄당 40 자, 500 줄을 가정하면 전체 문자열 크기는 ~ 20K가됩니다. 그 시점에서 20K 복사본의 오버 헤드로 인해 프로그램이 느려집니다.

1

이것이 StringBuilder에 대해 울부 짖는 동안 나는 그 것이 주 범인이라고 생각하지 않습니다. 오히려 우리는 지수 런타임이있는 코드 조각을 가지고 있습니다.

나는 염두에두고있는 것은 foundSpot을 계산하는 코드입니다. 코드를 올바르게 읽는다면 O (n^2)이고 나머지는 O (n)입니다.

조언 세 부분 :

1) 리 팩터! 이 루틴은 WAY입니다. 나는 "foundSpot을 계산하는 코드"를 참조 할 필요가 없어야합니다. 이름이있는 루틴이어야합니다. 여기에 최소한 4 개의 루틴이 있습니다.

2) Stringbuilder.

3) 검색 루틴을 정리해야합니다. 루프를 반복 할 때마다 반복 계산을 많이하고 있습니다. 적용 할 테스트를 파악하지 않으려는 경우가 아니라면 어떤 이유로 든 검색 성능이 좋은 것으로 처리해야합니다. 에).

+0

나는 foundAll을 할당하는 코드가 천천히 빨라지 리라 생각했다. 결과가 거의 끝나는 줄 resultTable.Rows.RemoveAt (foundSpot); 메인 루프를 통해 매번 가능성의 수를 줄입니다. – newuser

+0

또는 각 고유 식별자 (한 줄에 하나씩)에 대한 쿼리를 작성하고 주 루프의 각 반복에 대해 SQL DB에서 한 줄을 요청하는 것이 더 빠르다고 생각합니까? – newuser

1

새 텍스트는 추가 되었습니까? 그렇다면 파일 스트림에 기록하지 않는 이유는 무엇입니까? 또한 try catch를 추가하는 것을 잊지 마십시오. 따라서 앱이 터지면 파일 스트림을 닫을 수 있습니다.

또한 SubString 호출을 꺼내면 두 번째 루프가 빨라질 수 있습니다. 그 일을 반복해서 할 이유가 없습니다.

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

제공 한 두 가지 코드 예제를 구현했지만 새로운 문제가 있습니다. 내 메인 포스트에 대한 수정 내용을 확인해 주시겠습니까? – newuser

+0

https://gist.github.com/ –

+0

[link] (https://gist.github.com/822727)로 코드를 다시 게시하십시오. 실제로 제가 위에 언급 한 문제를 해결했습니다. 나의 유일한 느린 문제는 FindLine() 함수가 항상 -1을 반환하고 좋은 데이터가 전달된다는 것입니다. – newuser

관련 문제