Парсинг: загрузка в память или использование потока - PullRequest
0 голосов
/ 11 августа 2010

Я пишу небольшой анализатор и хотел бы знать преимущества и недостатки различных способов загрузки данных для анализа.Два способа, о которых я подумал:

  • Загрузить содержимое файла в строку, затем проанализировать строку (получить доступ к символу в позиции массива)
  • Анализировать как чтение потока файла(fgetc)

Первая позволяет мне иметь две функции: одну для parse_from_file и parse_from_string, однако я считаю, что этот режим займет больше памяти.У последнего не будет такого недостатка в использовании большего количества памяти.

У кого-нибудь есть какие-либо советы по этому вопросу?

Ответы [ 3 ]

2 голосов
/ 11 августа 2010

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

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

Хорошим балансом является наличие большого кругового буфера (x * 2 * 4096 хорошего размера), который вы загружаете с данными файла, а затем считываете из вашего токенизатора. Всякий раз, когда данные блока передаются вашему токенизатору (и вы знаете, что он не будет сдвинут назад), вы можете пополнить этот блок новыми данными из файла и обновить некоторую информацию о расположении буфера.

Еще одна вещь, которую следует учитывать, - есть ли шанс, что токенизатор когда-нибудь понадобится использовать для чтения из канала или от человека, набирающего текст напрямую. В этих случаях ваши операции чтения могут вернуть меньше данных, чем вы запрашивали, без их нахождения в конце файла, а упомянутый выше метод буферизации становится более сложным. Буферизация stdio хороша для этого, поскольку ее можно легко переключить в / из буферизации строки или блока (или без буферизации).

Использование gnu fast lex (flex, но не Adobe Flash) или аналогичного может значительно облегчить проблему со всем этим. Вы должны использовать его для генерации кода C для вашего токенизатора (лексический анализ).

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

0 голосов
/ 11 августа 2010

Наиболее эффективным в системе POSIX, вероятно, не будет ни один из двух (или вариант первого, если вам нравится): просто сопоставьте файл только для чтения с mmap и затем проанализируйте его. Современные системы достаточно эффективны, поскольку они предварительно выбирают данные, когда обнаруживают потоковый доступ и т. Д., Несколько экземпляров вашей программы, которые анализируют один и тот же файл, получат одинаковые физические страницы памяти и т. Д. И интерфейсы относительно просты в обращении, Я думаю.

0 голосов
/ 11 августа 2010

Рассмотрите возможность использования lex (и, возможно, yacc, если язык вашей грамматики соответствует его возможностям).Lex позаботится обо всех подробностях лексического анализа и создаст эффективный код.Вы, вероятно, можете сократить его объем памяти на несколько байтов, но сколько усилий вы хотите потратить на это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...