Какой лучший способ прочитать и проанализировать большой текстовый файл по сети? - PullRequest
9 голосов
/ 26 сентября 2008

У меня есть проблема, которая требует, чтобы я проанализировал несколько файлов журнала с удаленного компьютера. Есть несколько осложнений: 1) Файл может использоваться 2) Файлы могут быть довольно большими (100 Мб +) 3) Каждая запись может быть многострочной

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

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

Два основных вопроса: 1) Как ускорить передачу файла (Сжатие? Локальная передача даже необходима? Могу ли я прочитать используемый файл другим способом?) 2) Как мне работать с многострочными записями при разделении строк между потоками?

ОБНОВЛЕНИЕ: причина, по которой я не выполнил очевидный синтаксический анализ серверной причины, заключается в том, что я хочу иметь как можно меньше влияния на процессор. Я не хочу влиять на производительность системы, которую я тестирую.

Ответы [ 9 ]

2 голосов
/ 26 сентября 2008

Если вы читаете последовательный файл, вы хотите читать его построчно по сети. Вам нужен способ передачи, способный к потоковой передаче. Вам нужно будет пересмотреть свою технологию потокового ввода-вывода, чтобы понять это.

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

Другой замечательный вариант - разместить анализатор журнала на сервере и загрузить результаты.

1 голос
/ 26 сентября 2008

Если вы можете скопировать файл, вы можете прочитать его. Поэтому нет необходимости копировать его в первую очередь.

РЕДАКТИРОВАТЬ : используйте класс FileStream для большего контроля над режимами доступа и совместного использования.

new FileStream("logfile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)

должен сделать трюк.

1 голос
/ 26 сентября 2008

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

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

Улучшения в скорости синтаксического анализа (если таковые имеются) за счет использования многопоточности будут подавлены сравнительной скоростью передачи по сети.

Если вы решили передать свои файлы перед их синтаксическим анализом, вам следует рассмотреть возможность использования сжатия «на лету» во время передачи файлов. Например, доступны серверы sftp, которые будут выполнять сжатие на лету. На локальном конце вы можете использовать что-то вроде libcurl для выполнения клиентской части передачи, которая также поддерживает распаковку на лету.

1 голос
/ 26 сентября 2008

Использовать сжатие для передачи.

Если ваш синтаксический анализ действительно замедляет вас, и у вас есть несколько процессоров, вы можете разбить работу синтаксического анализа, вам просто нужно сделать это умным способом - иметь детерминированный алгоритм, за который работники отвечают за работу с неполные записи. Предполагая, что вы можете определить, что строка является частью середины записи, например, вы можете разбить файл на N / M сегментов, каждый из которых отвечает за M строк; когда одно из заданий определяет, что его запись не завершена, ему просто нужно продолжить чтение, пока не достигнет конца записи. Когда одно из заданий определяет, что оно читает запись, для которой оно не имеет начала, оно должно пропустить запись.

1 голос
/ 26 сентября 2008

Полагаю, это зависит от того, насколько он «удаленный». 100 МБ в 100 МБ локальной сети будет около 8 секунд ... до гигабита, и вы получите его примерно за 1 секунду. $ 50 * 2 за карты и $ 100 за коммутатор - очень дешевое обновление, которое вы могли бы сделать.

Но, предполагая, что это еще дальше, вы сможете открыть его в режиме только чтения (как вы читаете, когда копируете). SMB / CIFS поддерживает чтение блоков файлов, поэтому в этот момент вы должны передавать файл (конечно, вы фактически не сказали, как вы обращались к файлу - я просто предполагаю, что SMB).

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

1 голос
/ 26 сентября 2008

Самый простой способ, учитывая, что вы уже копируете файл, - это сжать его перед копированием и распаковать после завершения копирования. Вы получите огромный выигрыш при сжатии текстовых файлов, потому что алгоритмы zip обычно работают с ними очень хорошо. Кроме того, существующая логика синтаксического анализа может быть сохранена без необходимости подключения к удаленному сетевому считывателю текста.

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

0 голосов
/ 16 февраля 2019

Данный ответ не удовлетворяет меня, и, возможно, мой ответ поможет другим не думать, что это слишком сложно, или многопоточность не выиграет в таком сценарии. Возможно, это не ускорит передачу, но в зависимости от сложности вашего анализа это может ускорить анализ / или анализ проанализированных данных.

Это действительно зависит от деталей вашего анализа. Какую информацию вам нужно получить из файлов журнала? Эта информация похожа на статистику или зависит от нескольких сообщений журнала? У вас есть несколько вариантов:

  • Проанализировать несколько файлов одновременно было бы проще всего, я думаю, у вас есть файл в качестве контекста и вы можете создать один поток на файл
  • другая опция, как упоминалось ранее, это использовать сжатие для связи по сети
  • вы также можете использовать помощник, который разбивает файл журнала на строки, которые принадлежат друг другу в качестве первого шага, а затем с несколькими потоками обрабатывают эти блоки строк; Разбор этих зависимых строк должен быть достаточно простым и быстрым.

Очень важно в таком сценарии измерить фактическое узкое место. Если узким местом является сеть, вы не выиграете от чрезмерной оптимизации парсера. Если ваш парсер создает много объектов одного типа, вы можете использовать шаблон ObjectPool и создавать объекты с несколькими потоками. Попробуйте обработать ввод, не выделяя слишком много новых строк. Часто парсеры пишутся с использованием большого количества string.Split и так далее, это не так быстро, как могло бы быть. Вы можете перемещаться по потоку, проверяя поступающие значения, не читая всю строку и не разделяя ее снова, а непосредственно заполняя объекты, которые вам понадобятся после завершения анализа.

Оптимизация почти всегда возможна, вопрос в том, сколько вы получаете за то, какой вклад и насколько важен ваш сценарий.

0 голосов
/ 26 сентября 2008

я думаю, что использование сжатия (deflate / gzip) поможет

0 голосов
/ 26 сентября 2008

Я использовал SharpZipLib для сжатия больших файлов перед их передачей через Интернет. Так что это один из вариантов.

Другой идеей для 1) было бы создать сборку, которая запускается на удаленной машине и выполняет там разбор. Вы можете получить доступ к сборке с локальной машины, используя удаленное взаимодействие .NET. Удаленная сборка должна быть службой Windows или размещаться в IIS. Это позволит вам хранить копии файлов журналов на одном компьютере, и теоретически для их обработки потребуется меньше времени.

...