2011-10-23 5 views
2

私は100Mbのテキストファイルを持っていますので、すべての行で特別な単語をチェックする必要があります。 私はそれを行うための速い方法を探しています。Cでファイルを高速に検索して検索する方法を探しています#

ので、私は10にファイルを分割:

public void ParseTheFile(BackgroundWorker bg) 
    { 

     Lines = File.ReadAllLines(FilePath); 
     this.size = Lines.Length; 
     chankSise=size/10; 

     reports reportInst = new reports(bg,size); 

     ParserThread [] ParserthreadArray = new ParserThread[10]; 

     for (int i = 0; i <ParserthreadArray.Length; i++) 
     { 
      ParserthreadArray[i] = new ParserThread((reportInst)); 
      ParserthreadArray[i].Init(SubArray(Lines,i * chankSise, chankSise), OutputPath); 

     } 

     Thread oThread0 = new Thread(ParserthreadArray[0].run); 
     oThread0.IsBackground = true; 
     Thread oThread1 = new Thread(ParserthreadArray[1].run); 
     oThread1.IsBackground = true; 
     Thread oThread2 = new Thread(ParserthreadArray[2].run); 
     oThread2.IsBackground = true; 
     Thread oThread3 = new Thread(ParserthreadArray[3].run); 
     oThread3.IsBackground = true; 
     Thread oThread4 = new Thread(ParserthreadArray[4].run); 
     oThread4.IsBackground = true; 
     Thread oThread5 = new Thread(ParserthreadArray[5].run); 
     oThread5.IsBackground = true; 
     Thread oThread6 = new Thread(ParserthreadArray[6].run); 
     oThread6.IsBackground = true; 
     Thread oThread7 = new Thread(ParserthreadArray[7].run); 
     oThread7.IsBackground = true; 
     Thread oThread8 = new Thread(ParserthreadArray[8].run); 
     oThread8.IsBackground = true; 
     Thread oThread9 = new Thread(ParserthreadArray[9].run); 
     oThread9.IsBackground = true; 

     oThread0.Start(); 
     oThread1.Start(); 
     oThread2.Start(); 
     oThread3.Start(); 
     oThread4.Start(); 
     oThread5.Start(); 
     oThread6.Start(); 
     oThread7.Start(); 
     oThread8.Start(); 
     oThread9.Start(); 

     oThread0.Join(); 
     oThread1.Join(); 
     oThread2.Join(); 
     oThread3.Join(); 
     oThread4.Join(); 
     oThread5.Join(); 
     oThread6.Join(); 
     oThread7.Join(); 
     oThread8.Join(); 
     oThread9.Join(); 

これは初期化方法であって

public void Init(string [] olines,string outputPath) 
    { 
     Lines = olines; 
     OutputPath = outputPath+"/"+"ThreadTemp"+threadID; 
    } 

このサブアレイ方法であって、

public string [] SubArray(string [] data, int index, int length) 
    { 
     string [] result = new string[length]; 
     Array.Copy(data, index, result, 0, length); 
     return result; 
    } 

及び各スレッドがこれを行います:

public void run() 
    { 

     if (!System.IO.Directory.Exists(OutputPath)) 
     { 
      System.IO.Directory.CreateDirectory(OutputPath); 
      DirectoryInfo dir = new DirectoryInfo(OutputPath); 
      dir.Attributes |= FileAttributes.Hidden; 
     } 



     this.size = Lines.Length; 
     foreach (string line in Lines) 
     { 



      bgReports.sendreport(allreadychecked); 

      allreadychecked++; 
      hadHandlerOrEngine = false; 
      words = line.Split(' '); 
      if (words.Length>4) 
      { 
       for (int i = 5; i < words.Length; i++) 
       { 
        if (words[i] == "Handler" | words[i] == "Engine") 
        { 

         hadHandlerOrEngine = true; 
         string num = words[1 + i]; 
         int realnum = int.Parse(num[0].ToString()); 
         cuurentEngine = (realnum); 
         if (engineArry[realnum] == false) 
         { 
          File.Create(OutputPath + "/" + realnum + ".txt").Close(); 
          engineArry[realnum] = true; 

         } 
         TextWriter tw = new StreamWriter(OutputPath + "/" + realnum + ".txt", true); 
         tw.WriteLine(line); 
         tw.Close(); 

         break; 
        } 
       } 

      } 

      if (hadHandlerOrEngine == false) 
      { 
       if (engineArry[cuurentEngine] == true) 
       { 
        TextWriter tw = new StreamWriter(OutputPath + "/" + cuurentEngine + ".txt", true); 
        tw.WriteLine(line); 
        tw.Close(); 
       } 

      } 

     } 

私の質問は、あなたはおそらく、IOがバインドされているより速く、この実行

+0

http://incubator.apache.org/lucene.net/? – agibalov

答えて

7

あなたのInit方法を示していないが、現時点では、それはあなたのスレッドの各が実際にラインのすべてをチェックされますのように見えます。さらに、それらのすべてが同じファイルに書き込もうとしているように見えますが、例外安全な方法(usingステートメントを使用)でそうしないように見えます。

編集:さて、今度はInitが表示されますが、SubArrayは表示されません。おそらく、それは単に配列の塊をコピーするだけです。

スレッドの使用を避けるとどのくらい遅くなりますか?間違いなく遅すぎますか?あなたの目標は何ですか?その時点でメモリ/ CPUに完全にバインドされているので、10スレッドを使用すると助けになることはありません。 (すべてのスレッドを開始するために多くのコードを繰り返さないようにする必要があります。なぜそのコレクションを使用していないのですか?)

+0

私は自分のInitメソッドを添付していますが、ここでは各スレッドにファイルを分割します: 'for(int i = 0; i MoShe

+0

@MoShe:さて、私たちは' SubArray'メソッドを見逃しています... –

+0

サブアレイメソッドを追加しました – MoShe

6

を作るためにどのような方法がありますので、私は、複数のスレッドがはるかに支援するつもりされていないことを推測すると思います。 (あなたのプログラムはあなたのプログラムではほとんどの時間をここで費やしています:Lines = File.ReadAllLines(FilePath);実際に解析する時間はそれほど長くないので、測定してください)。すべてのものを単一のパーサスレッドに渡します。

MemoryMappedFile(これは.NET 4の場合)は、すべてのソースデータのコピーを作成する必要がないため、IOの一部を助けるはずです。

+1

読み取り用と書き込み用の2つのスレッドを持つこともできます。ReadAllLinesを小さな部分のサイクル読み取りに変更すると、ファイルが完全に読み取られるのを待たずに検索を開始できます。 –

1

有用と思われるものをお勧めします。誰かが言ったように、複数のスレッドがファイルを読み込むように割り当てても、それはI/Oアクティビティのほうが多いので、この場合はOS FileManagerにキューイングされます。しかし、間違いなく利用可能なI/O completion threadのためにasync I/Oリクエストを置くことができます。

ファイルの処理については、Memory-mapped files を使用することをおすすめします。メモリマップファイルは、かなり大きなファイルの任意のチャンクファイル(view)に繰り返し/別々にアクセスする必要があるシナリオに最適です。あなたのシナリオでは、メモリマップされたファイルは、チャンクが到着/処理されていない場合にファイルを分割/アセンブルするのに役立ちます。 私は現時点で便利な例はありません。次の記事Memory Mapped Filesをご覧ください。