Почему `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 может быть скомпилирован в код, а не в данные, он потенциально может работать немного быстрее и получить выгоду от оптимизации компилятора. Но в будущем необходимо провести дополнительные исследования, чтобы знать наверняка.