В 2010 году, работая в MathWorks над тем, что стало MATLAB Production Server, я написал анализатор протокола HTTP/1.1, который мог анализировать запрос сервера менее чем за 5 микросекунд на моей рабочей станции Xeon GNU/Linux с тактовой частотой 3 ГГц. Этот код был основан на общей структуре генератора синтаксического анализатора C++, которую я разработал для проекта, которая допускала каждую строку BNF из RFC 2616 и 2396 (HTTP/1.1 и URI соответственно; видите, мне даже не нужно их искать; вот как много раз я набирал их в течение этого месяца), чтобы они были точно переведены в одно C++ typedef, правильность которого легко проверяется во время проверки кода. Мы даже процитировали источник RFC в комментарии к коду. Это молниеносно быстрая, автономная, полностью универсальная цель, и мы сделали это до C++11. В этой серии будет документирована переработанная версия этого (и много других интересных вещей в области веб-инфраструктуры), которая стала еще лучше, с использованием C++14.

Прежде чем пойти по маршруту «создать», я огляделся. Большинство «веб-серверов» с нативным кодом (Apache httpd, nginx) не хотят использоваться в качестве библиотек, что было требованием. Даже если их можно было принудить, они принесли с собой собственный уровень абстракции платформы (например, APR==Apache Portable Runtime), а мы использовали Boost плюс базовые библиотеки MathWorks или «fl». Слишком много уровней абстракции платформы делают вашу архитектуру грустной.

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

Поэтому я отвернулся от пути «купить» и начал рассматривать свои варианты создания первой части, настоящего парсера протокола HTTP. Boost.Spirit — очевидный выбор, и я на самом деле продвинулся в этом довольно далеко. Однако время компиляции вскоре стало ужасающим, ошибки компиляции тем более, а некоторые из наших компиляторов (кхм, MSVC) просто отказывались даже компилировать код, взбивая около 10 минут, прежде чем вылететь с сообщением, которое сводилось к «Я искал где-то в этом месте вашего кода… попробуйте сказать это по-другому…» Спасибо.

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

Я публикую этот выпуск одновременно с первым в серии, содержащим фактический технический контент, поэтому, если я удовлетворил ваш аппетит (на который, надеюсь, у меня есть), вы можете прочитать о том, как эта штука на самом деле работает, в части 1. !