LINUX.ORG.RU

Как минимум есть PEGTL. Но вот нам пришлось свой лисапед для C++14 сделать, чтобы исключения не бросались при ошибках разбора.

eao197 ★★★★★
()

boost::spirit - это peg-парсер. Как эксперт по умению посылать (ничего из этого не использовал) рекомендую https://github.com/topics/peg?l=c%2B%2B

anonymous
()
Ответ на: комментарий от xaizek

Оу, и правда, чет я «пошёл по ссылке» и пришёл в XST.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

А почему выбрали его а не сабж?

Нам нужен был несложный инструмент, в котором бы:

  • информирование об ошибках парсинга шло через возвращаемые значения, а не через исключения. Исключения просаживают производительность, а т.к. нужно было парсить приходящие извне данные, то заранее не предугадаешь, с какой частотой ошибки будут возникать;
  • хотелось имееть более удобный способ получать разобранные значения нежели syntax actions, как в spirit и pegtl;
  • не было тяжелых зависимостей;
  • реализация всего этого дела была header-only (т.к. нам нужно было это все в header-only либе использовать).

В итоге сделали свое и не стали брать ни spirit, ни pegtl.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

А можешь ткнуть носом как его кормить чанками из асинхронного потока данных? Аля тем, что считалось после select.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

А можешь ткнуть носом как его кормить чанками из асинхронного потока данных?

Кого кормить?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

А тьфу-ты, чукча не читатель чет сегодня. Ты мне про ваш лисапед рассказываешь, а я про pegtl спрашиваю :)

Ещё вот интересно - а вы замеряли просадку в производительности и частоту ошибок в приходящих данных?

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Ещё вот интересно - а вы замеряли просадку в производительности и частоту ошибок в приходящих данных?

Не в этом конкретном случае, но в этом же проекте у нас было так, что по недосмотру начинали выскакивать исключения, тут же ловились и обрабатывались. При этом падение было где-то раз в 10, если не ошибаюсь. Т.е. буквально на бенчмарках показатели падали где-то со 100K req/sec до 10-15K.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

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

Но вообще - этож явно не интернет был?

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Но вообще - этож явно не интернет был?

Так никакого секрета нет, нам нужно было в RESTinio парсить HTTP-заголовки. По грамматикам из RFC. А уж что в этих заголовках от клиента может прилететь – хз. Могут тупо по недосмотру неправильно значения заголовков формировать и тогда ошибки парсинга будут в 100% случаев.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от eao197

по недосмотру начинали выскакивать исключения, тут же ловились и обрабатывались. При этом падение было где-то раз в 10, если не ошибаюсь. Т.е. буквально на бенчмарках показатели падали где-то со 100K req/sec до 10-15K

Так это, в плюсах что ли до сих пор невменяемо медленные исключения? Я думал, это уже сто лет в обед как исправили в флагманских компиляторах.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Так это, в плюсах что ли до сих пор невменяемо медленные исключения?

Исключения в C++ сейчас практически zero cost если они не бросаются.

Сам выброс исключения очень дорогой.

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

Так что приходится оценивать, насколько часто придется информовать об ошибках. И если часто, то пока что исключения вне игры :(


На самом деле даже если исключения не бросаются, они все равно не zero cost, т.к. в программе приходится хранить таблицу адресов, благодаря которой при выбросе исключения компилятор понимает, куда нужно передавать управление (вроде бы правильно сформулировал).

eao197 ★★★★★
()

Альтернатив, которые также сильно жрут процессор при компиляции, пока не придумали.

Urechis_Unicinctus
()
Ответ на: комментарий от eao197

Сам выброс исключения очень дорогой.

А с этим можно что-либо сделать, хотя бы в теории, или это фундаментальное свойство самого механизма (вытекающее из необходимых свойств исключений по стандарту)?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

это фундаментальное свойство самого механизма (вытекающее из необходимых свойств исключений по стандарту)?

Насколько я понимаю, это фундаментальное свойство текущего подхода к исключениям в C++.

В 2018-ом году Саттер высказал предложение по переходу к другому механизму, «Zero-overhead deterministic exceptions: Throwing values». Информация по этому предложению доступна здесь: https://github.com/cplusplus/papers/issues/310 Последняя версия самого предложения, насколько я понимаю, здесь: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf

Реакция на первую версию предложения была неоднозначная. В частности, многих напряг момент со слишком жестким подходом к невозможности выделения памяти (т.е. terminate вместо bad_alloc). Поэтому в последующих ревизиях этот момент попытались смягчить.

В C++20 не попало. А вот при работе над C++23 это предложение будет рассматриваться. И, вроде бы, по словам Полухина, на этот момент завязано еще и предложение по включению в стандарт типа std::expected. Если примут механизм Саттера для исключений, то особого смысла в std::excepted не будет, т.к. новые исключения и будут чем-то вроде std::expected.

PS. Могу чего-то напутать, т.к. в последний раз к этой теме возвращался где-то год назад.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Ну и что, что приходится хранить таблицу. Она вроде никак не влияет на производительность (сам факт ее наличия).

Да, убеждался на собственном опыте, что if медленнее чем исключения (если конечно исключения используются для исключительных ситуаций). Причем исключения тормозят только если они выпали, а if тормозит как в случаи ошибки, так и при нормальном проходе. Может likely решит частично эту проблему..

zerhud
()

Есть еще boost::spirit::x3 он хорош

zerhud
()
Ответ на: комментарий от zerhud

Она вроде никак не влияет на производительность (сам факт ее наличия).

Большая таблица, которая время от времени будет извлекаться из памяти в кэш не есть хорошо для производительности.

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

А я с этим и не спорил. Просто говорил о том, что если процент исключений велик, то исключения, к сожалению, сильно тормознее кодов возврата.

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

eao197 ★★★★★
()
Ответ на: комментарий от intelfx

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

lovesan ★★
()
Ответ на: комментарий от lovesan

Так при использовании кодов возврата на стеке лежат те же самые объекты с RAII и у них вызываются те же самые деструкторы.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Насколько я понимаю, это фундаментальное свойство текущего подхода к исключениям в C++.

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

intelfx ★★★★★
()
Ответ на: комментарий от lovesan

Так при использовании кодов возврата на стеке лежат те же самые объекты с RAII и у них вызываются те же самые деструкторы

++

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

это ортогональные вещи. в случае non-local exit используется качественно другая механика, и тут это все говно начинает мешать

lovesan ★★
()
Ответ на: комментарий от intelfx

А почему? На что конкретно тратится время?

ЕМНИП, на две вещи:

  1. Аллокация объекта-исключения в динамической памяти.
  2. Проход в обратном порядке по расположенным выше по стеку блокам catch и поиск совпадения типа в catch с типом брошенного исключения (для чего применяется поиск с использованием механизмов RTTI).

Вот эти две вещи являются наиболее дорогими.

Там же эти таблицы вроде бы содержат готовую информацию о том, до какого места нужно разматывать стек?

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

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

eao197 ★★★★★
()
3 декабря 2020 г.
Ответ на: комментарий от eao197

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

Если контачишь с ним - порекомендуй тот же калькулятор в туториал закинуть, будет понятней, чем оно от dsl для регулярок отличается.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Не сказал бы, что контактирую. Сперва новость встретилась на Meeting C++, затем всплыла на Reddit-е.

eao197 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.