У меня есть большое и сложное регулярное выражение C#, которое работает нормально при интерпретации, но немного медленнее. Я пытаюсь ускорить это, установив RegexOptions.Compiled
, и это, кажется, занимает около 30 секунд в первый раз и сразу после этого. Я пытаюсь это отрицать, сначала компилируя регулярное выражение на сборку, поэтому мое приложение может быть как можно быстрее.Почему мое регулярное выражение намного медленнее компилируется, чем интерпретируется?
Моя проблема в том, когда сбор задержка происходит, будь то компилируется в приложении:
Regex myComplexRegex = new Regex(regexText, RegexOptions.Compiled);
MatchCollection matches = myComplexRegex.Matches(searchText);
foreach (Match match in matches) // <--- when the one-time long delay kicks in
{
}
или с помощью Regex.CompileToAssembly заранее:
MatchCollection matches = new CompiledAssembly.ComplexRegex().Matches(searchText);
foreach (Match match in matches) // <--- when the one-time long delay kicks in
{
}
Это делает компиляции для сборки в основном бесполезно, поскольку я все еще получаю задержку при первом вызове foreach
. Я хочу, чтобы вся компиляция была выполнена во время компиляции (при вызове Regex.CompileToAssembly), а не во время выполнения. Где я иду не так?
(Код, который я использую для компиляции сборки, аналогичен http://www.dijksterhuis.org/regular-expressions-advanced/, если это необходимо).
Edit:
Должен ли я использовать new
при вызове скомпилированной сборки в new CompiledAssembly.ComplexRegex().Matches(searchText);
? Однако он дает ошибку «ссылка на объект».
Update 2
Спасибо за ответы/комментарии. Регулярное выражение, которое я использую, довольно длинное, но в основном прямолинейное, список тысяч слов, каждый из которых разделен символом |. Я не вижу, чтобы это было проблемой возврата. Строка subject может быть длиной всего одна буква, и она все равно может привести к задержке компиляции. Для регулярного выражения RegexOptions.Compiled это займет более 10 секунд, чтобы выполнить, когда регулярное выражение содержит 5000 слов. Для сравнения, не скомпилированная версия регулярного выражения может принимать 30 000 слов и выполнять их практически мгновенно.
После этого много испытаний на это, что я думаю, что я узнал, это:
- Не используйте RegexOptions.Compiled, когда ваше регулярное выражение имеет много альтернатив - это может быть очень медленно, чтобы компиляции.
- .Net будет использовать lazy evaluation for regex, если возможно, и AFAI может видеть, что это также расширяет (по крайней мере до некоторой степени) компиляцию регулярных выражений. Регулярное выражение будет полностью скомпилировано только тогда, когда оно должно быть, и, похоже, не существует способа форсировать компиляцию раньше времени.
- Regex.CompileToAssembly будет намного полезнее, если бы регулярные выражения могли быть полностью скомпилированы, похоже, что они не имеют никакого смысла.
Пожалуйста, исправьте меня, если я ошибаюсь или что-то не хватает!
Возможно, вам стоит попробовать поделиться фактическим выражением и примерным вводом, который дает вам такое поведение. – driis
Спасибо за сообщение. Имел ту же проблему с некоторым Regex Twitter, перенесенным с Java на .NET. И RegexOptions.Compiled, и .CompileToAssembly заставляли приложение висеть в течение ~ 10 секунд при первом попытке сопоставления. Удалено Regex.Compiled и все мгновенно. – LongZheng
MSDN добавила статью о лучших практиках для .NET 4, которая адресовала [regex's compiled to assemblysies] (http://msdn.microsoft.com/en-us/library/gg578045.aspx#sectionToggle4). –