複数のファイルで文字列を検索する最良の方法は何ですか?
現在、各ファイルに対して foreach ループを実行していますが、4000 以上のファイルすべてを処理するには最大 4 ~ 5 分かかることに気付きました。
これを行うためのある種の並列方法はありますか?
複数のファイルで文字列を検索する最良の方法は何ですか?
現在、各ファイルに対して foreach ループを実行していますが、4000 以上のファイルすべてを処理するには最大 4 ~ 5 分かかることに気付きました。
これを行うためのある種の並列方法はありますか?
これを行う最善の方法は、Producer Consumer モデルです。これで行うことは、1 つのスレッドがハード ドライブから読み取り、データをキューにロードし、不確定な数の他のスレッドがデータを処理することです。
だからあなたの古いコードはこれだったとしましょう
foreach(var file in Directory.GetFiles(someSearch)
{
string textToRead = File.ReadAllText(file);
ProcessText(textToRead)
}
新しいコードは
var collection = new BlockingCollection<string>(); //You may want to set a max size so you don't use up all your memory
Task producer = Task.Run(() =>
{
foreach(var file in Directory.GetFiles(someSearch)
{
collection.Add(File.ReadAllText(file))
}
collection.CompleteAdding();
});
Parallel.ForEach(collection.GetConsumingEnumerable(), ProcessText); //Make sure any actions ProcessText does (like incrementing any variables in the class) is done in a thread safe manner.
これにより、1 つのスレッドがハード ドライブから読み取り、他のスレッドと I/O で競合することはなくなりますが、同時に読み取られたデータを複数のスレッドで処理できるようになります。
この検索を定期的に行う場合は、Solr などの検索エンジンを使用してファイルのインデックスを作成することを検討してください。ファイルがインデックス化された後、検索には数ミリ秒かかります。
たとえば、Lucene ライブラリを使用して、アプリに検索エンジンを埋め込むこともできます。
この操作は主に I/O バウンドになるため、並列処理によってパフォーマンスが向上することはありません。サードパーティの検索ライブラリを使用してファイルのインデックスを作成することもできますが、ソフトウェアに関してできることはそれだけです。ファイルを複数のドライブに分割し、ドライブごとに異なるスレッドを使用すると、オプションである場合、速度が向上する可能性があります。
ほとんどの時間は、ファイルがディスクから読み取られるまでの待機に費やされている可能性があります。そのような状況では、マルチスレッド化は大きな問題にはなりません。1 つのスレッドがディスク IO を待機するのではなく、複数のスレッドがディスク IO を待機するようになります。