Что происходит за кулисами, когда вы помечаете регулярное выражение как компилируемое? Чем это отличается / отличается от кэшированного регулярного выражения?
Используя эту информацию, как вы определяете, когда стоимость вычислений незначительна по сравнению с увеличением производительности?
Ответы:
RegexOptions.Compiled
поручает механизму регулярных выражений компилировать выражение регулярного выражения в IL с использованием облегченной генерации кода ( LCG ). Эта компиляция происходит во время строительства объекта и сильно замедляет его. В свою очередь совпадения с использованием регулярного выражения выполняются быстрее.Если вы не укажете этот флаг, ваше регулярное выражение будет считаться «интерпретированным».
Возьмите этот пример:
Он выполняет 4 теста по 3 различным регулярным выражениям. Сначала он проверяет одного однажды от матча (скомпилированный против не компилируется). Во-вторых, он проверяет повторяющиеся совпадения, которые используют одно и то же регулярное выражение.
Результаты на моей машине (скомпилированы в выпуске, без отладчика)
1000 одиночных матчей (построить Regex, Match и dispose)
1 000 000 совпадений - повторное использование объекта Regex
Эти результаты показывают, что скомпилированные регулярные выражения могут быть на 60% быстрее в случаях, когда вы повторно используете
Regex
объект. Однако в некоторых случаях его можно построить на 3 порядка медленнее.Это также показывает, что x64-версия .NET может быть в 5-6 раз медленнее, когда речь идет о компиляции регулярных выражений.
Рекомендуется использовать скомпилированную версию в случаях, когда
Гаечный ключ в работах, кеш Regex
Механизм регулярных выражений содержит кэш LRU, который содержит последние 15 регулярных выражений, которые были протестированы с использованием статических методов
Regex
класса.Например:
Regex.Replace
иRegex.Match
т. Д. Все используют кэш Regex.Размер кеша можно увеличить настройкой
Regex.CacheSize
. Он принимает изменения в размере в любое время в течение жизненного цикла вашего приложения.Новые регулярные выражения кэшируются только статическими помощниками в классе Regex. Если вы создаете свои объекты, кеш проверяется (для повторного использования и увеличения), однако создаваемое вами регулярное выражение не добавляется в кеш .
Этот кеш является тривиальным LRU-кешем, он реализован с использованием простого двойного связанного списка. Если вам доведется увеличить его до 5000 и использовать 5000 различных вызовов статических помощников, каждая конструкция регулярного выражения будет сканировать 5000 записей, чтобы увидеть, было ли оно ранее кэшировано. Вокруг проверки есть блокировка , поэтому проверка может уменьшить параллелизм и ввести блокировку потоков.
Число установлено достаточно низким, чтобы защитить себя от подобных случаев, хотя в некоторых случаях у вас может не быть иного выбора, кроме как увеличить его.
Моя настоятельная рекомендация не будет никогда передать
RegexOptions.Compiled
опцию статического помощника.Например:
Причина в том, что вы сильно рискуете пропустить кеш LRU, что приведет к очень дорогой компиляции. Кроме того, вы понятия не имеете, что делают библиотеки, от которых вы зависите, поэтому не имеете возможности контролировать или прогнозировать наилучший возможный размер кэша.
Смотрите также: блог команды BCL
Примечание : это актуально для .NET 2.0 и .NET 4.0. В 4.5 ожидаются некоторые изменения, которые могут привести к его пересмотру.
источник
Compiled
код веб-сайта, где я на самом деле храню статический (прикладной)Regex
объект. Таким образом,Regex
единственное должно быть создано один раз, когда IIS запускает приложение, а затем повторно используется тысячи раз. Это работает хорошо, пока приложение не перезагружается часто.Эта запись в блоге команды BCL дает хороший обзор: « Производительность регулярных выражений ».
Короче говоря, существует три типа регулярных выражений (каждый выполняется быстрее, чем предыдущий):
интерпретированы
быстро создавать на лету, медленно выполнять
скомпилирован (тот, о котором вы, кажется, спрашиваете)
медленнее создавать на лету, быстро выполнять (хорошо для выполнения в циклах)
предварительно скомпилированных
создавать во время компиляции вашего приложения (без штрафов за создание во время выполнения), быстро выполнить
Таким образом, если вы намереваетесь выполнить регулярное выражение только один раз или в не критически важном для производительности разделе вашего приложения (т. Е. Проверка пользовательского ввода), у вас все в порядке с вариантом 1.
Если вы намереваетесь запустить регулярное выражение в цикле (т. Е. Построчный анализ файла), вам следует перейти к варианту 2.
Если у вас есть много регулярных выражений, которые никогда не изменятся для вашего приложения и интенсивно используются, вы можете выбрать вариант 3.
источник
CompileModule
. Черт, мне нужно глубже взглянуть на новую платформу.Следует отметить, что производительность регулярных выражений начиная с .NET 2.0 была улучшена благодаря кэш-памяти MRU не скомпилированных регулярных выражений. Код библиотеки Regex больше не переосмысливает одно и то же не скомпилированное регулярное выражение каждый раз.
Так что потенциально больше производительности штраф с обобщаются и на лету регулярного выражения. В дополнение к более медленным временам загрузки система также использует больше памяти для компиляции регулярного выражения в коды операций.
По сути, текущий совет: либо не компилируйте регулярные выражения, либо скомпилируйте их заранее в отдельную сборку.
Ссылка: BCL Team Blog Производительность регулярных выражений [David Gutierrez]
источник
1) Команда библиотеки базового класса на скомпилированном регулярном выражении
2) Coding Horror, ссылаясь на # 1 с некоторыми хорошими моментами в обмене
источник
Я надеюсь, что приведенный ниже код поможет вам понять концепцию функций re.compile
источник