Производительность

Некоторые элементы, которые встречаются в шаблонах, более эффективны, чем другие. Например, символьный класс [aeiou] работает гораздо эффективнее набора альтернатив (a|e|i|o|u). Как правило, более простая конструкция наболее эффективна. Книга Джеффри Фридла содержит много обсуждений вопроса оптимизации регулярных выражений.

Если шаблон начинается с .* и включили флаг PCRE_DOTALL, шаблон неявно заякоривается, поскольку шаблон может совпадать только в начале строки. Но если модификатор PCRE_DOTALL не включили, PCRE не может выполнить соответствующую оптимизацию, поскольку в этой ситуации метасимвол «.» не соответствует символу начала строки (если обрабатываемые данные содержат переводы строк, такой шаблон может соответствовать шаблону не от начала строки, а от позиции непосредственно после перевода строки). Например, применяя шаблон (.*) second к строке «first\nand second» (где \n — символ перевода строки), значение, которое захватил первый подшаблон, будет «and». Чтобы обработать все возможные точки соответствия, модуль PCRE пытается сопоставить шаблон после каждого символа перевода строки.

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

Избегайте шаблонов, которые содержат вложенные неограниченные повторения. Сопоставление таких шаблонов со строками, которые не содержат совпадений, занимает длительное время. Рассмотрим пример шаблона (a+)*

Он может соответствовать значению «aaaa» тридцатью тремя различными способами, и эта цифра очень быстро растёт при увеличении строки. (В примере квантификатор * может совпадать 0, 1, 2, 3 или 4 раза, и для каждого такого случая, кроме нуля, квантификатор + также может совпадать различное число раз.) Если остаток шаблона таков, что все совпадение терпит неудачу, модуль PCRE должен попробовать все возможные варианты совпадения, что может потребовать огромного количества времени.

За счёт оптимизации отлавливают наиболее простые случаи наподобие (a+)*b где следом идёт литеральный символ. Перед началом стандартной процедуры поиска модуль PCRE проверяет в следующей подстроке наличие символа «b», и если символа нет, попытка сопоставления немедленно завершается неудачей. Однако, когда последующего литерала нет, оптимизация не может быть применена. Разница заметна при сравнении поведения шаблона (a+)*\d с поведением приведённого выше шаблона. Первый определяет невозможность сопоставления практически сразу, при сопоставлении со строкой, которая состоит из символов «a», тогда как второй тратит длительное время на поиск в строках с длиной больше 20 символов.

To Top