Как написать 1GB файл эффективным способом С#

У меня есть .txt файл (содержит более миллиона строк), который составляет около 1 ГБ, и у меня есть один список строк, я пытаюсь удалить все строки из файла, который существует в списке строк, и создать новый файл, но он занимает много времени.

using (StreamReader reader = new StreamReader(_inputFileName))
{
   using (StreamWriter writer = new StreamWriter(_outputFileName))
   {
     string line;
     while ((line = reader.ReadLine()) != null)
     {
       if (!_lstLineToRemove.Contains(line))
              writer.WriteLine(line);
     }

    }
  }

Как повысить производительность моего кода?

Ответ 1

Вы можете получить некоторое ускорение, используя PLINQ для параллельной работы, также переключение с списка на хэш-набор также значительно ускорит проверку Contains(. HashSet является потокобезопасным для операций только для чтения.

private HashSet<string> _hshLineToRemove;

void ProcessFiles()
{
    var inputLines = File.ReadLines(_inputFileName);
    var filteredInputLines = inputLines.AsParallel().AsOrdered().Where(line => !_hshLineToRemove.Contains(line));
    File.WriteAllLines(_outputFileName, filteredInputLines);
}

Если неважно, что выходной файл находится в том же порядке, что и входной файл, вы можете удалить .AsOrdered() и получить некоторую дополнительную скорость.

Помимо этого вы действительно просто привязаны к вводу/выводу, единственный способ сделать это быстрее - получить более быстрые диски для его запуска.

Ответ 2

Код особенно медленный, потому что читатель и писатель никогда не выполняются параллельно. Каждый из них должен ждать другого.

Вы можете почти удвоить скорость операций с файлами, например, используя поток чтения и поток писем. Поместите a BlockingCollection между ними, чтобы вы могли общаться между потоками и ограничивать количество строк, которые вы буферизируете в памяти.

Если вычисление действительно дорого (это не в вашем случае), может помочь и третий поток с другим BlockingCollection, выполняющим обработку.

Ответ 3

Не используйте буферизованные текстовые процедуры. Используйте двоичные, небуферизованные библиотечные процедуры и сделайте размер вашего буфера как можно большим. Это, как сделать его самым быстрым.

Ответ 4

Из того, что я вижу, части "Чтение и запись" вашего кода обычно должны быть в порядке, быстрее, чем "15 минут" для 1gb, которые вы цитируете в своих комментариях. Я могу обрабатывать более 1 гб в минуту на своем ноутбуке, используя код чтения и записи. Я не могу сказать, что обработка, в которой вы пропустите определенные строки, хорошо оптимизирована или нет, но я ухожу от своей точки, которую я собираюсь сделать.

Поскольку используемый метод чтения и записи обычно должен быть "быстрым", я рекомендую вам принять следующую стратегию, чтобы определить максимальную скорость, на которую вы могли бы рассчитывать приблизиться, и где узкое место с вашей низкой скоростью.

  • Вручную скопируйте этот большой файл из области "Источник" в область "Место назначения". Обратите внимание на время, необходимое для выполнения копии. Если это время слишком медленное, ваша проблема, скорее всего, с компьютером, который вы используете. Но вы можете так же легко убить свою производительность, скопировав с сетевого диска или на сетевой диск или работая только на сетевом диске или что-то в этом роде (диски USB, диски, которые уже находятся под очень высокой нагрузкой ввода-вывода и т.д.).
  • Откорректируйте свой код, чтобы он просто читал файл и записывал файл без дополнительной обработки. Обратите внимание на время, необходимое для выполнения задачи. Если вы заметили большую разницу во времени, вам нужно сначала оптимизировать эту часть. Я вижу здесь несколько хороших предложений, и иногда ответ может быть экзотическим.
  • Если время между 1 и 2 почти одинаковое, а время хорошее и быстрое, тогда обработка, которую вы выполняете между чтением и записью, является проблемой. Вам нужно оптимизировать эту часть кода. Постепенно добавьте код обратно, пока не определите шею бутылки. Циклы, строковые операции, списки, словари могут убить ваше исполнение, но простая логическая ошибка может также. Я вижу здесь несколько предложений по работе с HashSet и т.д., Которые могут помочь ускорить потенциально медленные части вашего кода, но вам нужно понять, почему это происходит медленно, или посчастливилось попробовать случайные изменения (не рекомендуется).

Ответ 5

Считаете ли вы использование AWK

AWK - очень мощный инструмент для обработки текстовых файлов, вы можете найти дополнительную информацию о том, как фильтровать строки, соответствующие определенным критериям Фильтровать текст с помощью ASK