Поиск строк на совпадение в текстовых файлах C#
В общем, другу понадобился софт, который удаленно, на его сервере ищет из всех содержащихся там текстовых файлов совпадение по заданному слову. Я написал класс отвечающий за TCP соединение и вот тут вопрос по классу, который будет искать. В принципе все работает, даже системные ресурсы не так сильно жрет (за исключением процессора до 20%), но все же скорость поиска меня не устаревает, хочется побыстрее. Вот код и вопрос, как можно улучшить, ускорить его работу
foreach (string item in dirWork)
{
foreach (string item2 in SafeEnumerateFiles(item))
{
using (StreamReader _reader = new StreamReader(new BufferedStream(File.OpenRead(item2), 1024 * 1024)))
{
string line;
while ((line = await _reader.ReadLineAsync()) != null)
{
if (line.Contains(ItemSearch))
{
name.Add($"{Path.GetFileName(item2)}");
result.Add($"{line}");
}
}
}
}
}
dirWork содержит коллекцию папок лежащие на разных дисках. SafeEnumerateFiles(item) метод возвращает полную коллекцию всех файлов в папке и подпапках.
Ответы (1 шт):
Если вам нужна скорость, то я бы вот что попробовал
Убрал бы асинхронность. Асинхронность делает приложение более отзывачивым, но конкретная операция может стать медленней из за построения конечногго автомата и переключений контекста. Но это чисто догадка, я не проверял её правдивость.
Увеличил бы буфер. Один мегабайт таки это маловато. Я бы сделал магабайт 10-100 на поток
Обрабатывал бы файлы параллельно. При большои буфере в одном потоке когда файл считыватся, проц простаивает и когда данные обрабатываются - простаивает жесткий диск.
Вот пример
private IEnumerable<(string filename, string line)> GetFilieredLines(string file, string pattern)
{
using(var reader = new StreamReader( new BufferedStream( File.OpenRead(file), 10*1024*1024) ))
{
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
if(line.Contains(pattern)) yield return (file, line);
}
}
}
Как вызывать
var folder = @"D:\.....";
var results = Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)
.AsParallel()
.SelectMany(x=>GetFilieredLines(x, "public class"))
.Dump();
Вывод
