Почему `regex!` Не является оболочкой для `Regex::new`, предлагающей такую ​​же скорость соответствия регулярному выражению?

Rust Regex crate предлагает regex! расширение синтаксиса, которое позволяет компилировать регулярное выражение в течение стандартного времени компиляции. Это хорошо двумя способами:

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

К сожалению, документы говорят:

ВНИМАНИЕ: regex! плагин компилятора на порядки медленнее обычного Regex::new(...) использование. Вы не должны использовать плагин компилятора, если у вас нет особой причины для этого.

Это звучит как совершенно другой движок регулярных выражений, используемый для regex! чем для Regex::new(), Почему нет regex!() просто обертка для Regex::new() объединить преимущества обоих миров? Насколько я понимаю, эти плагины компилятора синтаксического расширения могут выполнять произвольный код; почему бы и нет Regex::new()?

1 ответ

Решение

Ответ очень тонкий: одна особенность макроса в том, что результат regex! можно поместить в статические данные, например так:

static r: Regex = regex!("t?rust");

Основная проблема заключается в том, что Regex::new() использует выделения кучи во время компиляции регулярных выражений. Это проблематично и потребует переписать Regex::new() двигатель также позволяет статическое хранение. Вы также можете прочитать комментарий Бернцуши об этой проблеме на Reddit.


Есть несколько советов о том, как улучшить regex!:

  • Брось static поддерживать и просто проверять строку регулярного выражения во время компиляции, все еще компилируя регулярное выражение во время выполнения
  • Держать static поддержка с помощью аналогичного трюка, как lazy_static! делает

По состоянию на начало 2017 года разработчики сосредоточены на стабилизации стандартного API для выпуска версии 1.0. поскольку regex! в любом случае требуется ночной компилятор, сейчас он имеет низкий приоритет.

Тем не менее, подход компилятор-плагин может предложить даже лучшую производительность, чем Regex::new(), что уже очень быстро: поскольку DFA в regex может быть скомпилирован в код, а не в данные, он потенциально может работать немного быстрее и получить выгоду от оптимизации компилятора. Но в будущем необходимо провести дополнительные исследования, чтобы знать наверняка.

Другие вопросы по тегам