Эффективность и ресурсозатратность регулярных выражений

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

44
16 комментариев

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

6
Ответить

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

3
Ответить

Самое полезное, что можно прочитать про регулярные выражения, это вот эту вот цитату за авторством Jamie Zawinski:

Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems.

Можно распечатать и повесить на стену. Контекст цитаты — времена, когда регулярные выражения были на пике популярности, и Perl был в большом почёте. Тогда было написано совершенно лютое количество абсолютно нечитаемого и полного багов говнокода с монстроузными выражениями в несколько строчек длиной, который было проще выкинуть и переписать по-человечески, чем пытаться сопровождать.

Если у тебя действительно есть задача, где вроде бы неудобно писать обычный код (т.е. ты делаешь что-то сложнее, чем проверку в духе "а есть ли в строчке символ @"), и в то же самое время не пытаешься решить с помощью регулярных выражений то, для чего по-хорошему надо бы написать нормальный парсер, то:

1. Пиши.
2. Замеряй производительность.

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

В целом есть куча бенчмарков, и можно посмотреть, какие библиотеки в целом обычно быстрые или в целом обычно медленные. Например все имплементации std::regex — это абсолютное беспросветное говнище, работающее раз так в 300 медленнее, чем надо (и это теперь не могут починить не ломая ABI, поэтому регулярные выражения из стандартной библиотеки C++ лучше просто никогда не трогать).

Например прикрепил табличку вот отсюда: https://github.com/HFTrader/regex-performance

Смотри, например, колонку rust_regex: в сотни раз быстрее std::regex почти везде, но работает совершенно чудовищно в одном конкретном случае, где все остальные справляются гораздо лучше.

Или pcre-jit — кажется, что в целом неплохо и без больших просадок, но иногда оказывается медленней rust_regex в несколько раз.

Я это к тому, что любая попытка угадывать производительность без измерений — очень плохая затея. Ну т.е. понятно, что если сделать выражение сильно сложнее, то наверное может быть будет медленней, но сложно сказать, на 5% будет медленней или в 100 раз.

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

5
Ответить

Спасибо, очень развернутый ответ, это круто

Ответить

По производительности по скорости только один совет: пиши так, чтобы выражение работало за один проход (без возвратов).
Вот тут, например, несколько советов: https://www.loggly.com/blog/five-invaluable-techniques-to-improve-regex-performance/

Немного не понял это:
не перегружать оперативкуРазве они занимают много памяти? При компиляции у тебя получается эквивалентный автоматный (или КС-) код.

2
Ответить

Если использовать дизьюнкцию, да. Но именно на больших данных. Под большими подразумеваю строки длинной больше 10^6 симвооов

Ответить

А, ещё пиши скобочки «(...)» только если тебе нужен захват подвыражения. Если не нужен, лучше используй математические скобки «(?:...)».
Я пишу на шарпе, там есть два режима у regex'ов: компилируемый и динамический. Если выражение используется кучу раз, то лучше за предкомпилировать.

1
Ответить