использование статического Regex. IsMatch по сравнению с созданием экземпляра Regex

Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition() 
== typeof(List<>);
42
задан Ben McNiel 6 January 2009 в 06:06
поделиться

6 ответов

В редком отклонении от моего типичного самомнения я - вид инвертирования меня на этом ответе.

Мой исходный ответ, сохраненный ниже, был основан на исследовании версии 1.1 платформы.NET. Это довольно позорно, так как.NET 2.0 отсутствовала больше трех лет во время моего ответа, и это содержало изменения в Regex класс, которые значительно влияют на различие между статическими методами и методами экземпляра.

В.NET 2.0 (и 4.0), помехи IsMatch функция определяется следующим образом:

public static bool IsMatch(string input, string pattern){
    return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
}

значительная разница здесь то, что мало true как третий аргумент. Это соответствует параметру, названному "useCache". Когда это верно, тогда проанализированное дерево получено от кэшируемого на втором и последующем использовании.

Это кэширование съедает most—, но не all— различия в производительности между статическими методами и методами экземпляра. В моих тестах помехи IsMatch метод был все еще приблизительно на 20% медленнее, чем метод экземпляра, но который только составил приблизительно половину второго увеличения, когда выполнено 100 раз по ряду 10 000 входных строк (для в общей сложности 1 миллиона операций).

Это 20%-е замедление может все еще быть значительным в некоторых сценариях. При нахождении себя regexing сотнями миллионов строк Вы, вероятно, захотите сделать каждый шаг, Вы можете для создания его более эффективным. Но я держал пари, что 99% времени, Вы используете конкретный Regex не больше, чем несколько разы, и дополнительная миллисекунда, которую Вы теряете статическому методу, не будет даже близко к значимому.

Опоры к [1 116] devgeezer, кто указал на это почти год назад, хотя никто, казалось, не заметил.

Мой старый ответ следует:

<час>

помехи IsMatch функция определяется следующим образом:

public static bool IsMatch(string input, string pattern){
    return new Regex(pattern).IsMatch(input);
}

И, да, инициализация Regex объект не тривиален. Необходимо использовать помехи IsMatch (или любые из других помех Regex функции) как быстрый ярлык только для шаблонов, которые Вы будете использовать только однажды. При многократном использовании шаблона это стоит того для многократного использования Regex объект, также.

относительно того, необходимо ли определить RegexOptions.Compiled, как предложил Jon Skeet, это - другая история. Ответ там: это зависит. Для простых шаблонов или для шаблонов использовал только несколько разы, это может быть быстрее для использования нескомпилированного экземпляра. Необходимо определенно представить перед решением. Стоимость компиляции объекта регулярного выражения является довольно большой действительно и не может стоить того.

<час>

Берут, как пример, следующее:

const int count = 10000;

string pattern = "^[a-z]+[0-9]+$";
string input   = "abc123";

Stopwatch sw = Stopwatch.StartNew();
for(int i = 0; i < count; i++)
    Regex.IsMatch(input, pattern);
Console.WriteLine("static took {0} seconds.", sw.Elapsed.TotalSeconds);

sw.Reset();
sw.Start();
Regex rx = new Regex(pattern);
for(int i = 0; i < count; i++)
    rx.IsMatch(input);
Console.WriteLine("instance took {0} seconds.", sw.Elapsed.TotalSeconds);

sw.Reset();
sw.Start();
rx = new Regex(pattern, RegexOptions.Compiled);
for(int i = 0; i < count; i++)
    rx.IsMatch(input);
Console.WriteLine("compiled took {0} seconds.", sw.Elapsed.TotalSeconds);

В [1 113], как перечислено, второй вывод является самым быстрым. Увеличение count к [1 115], и победы скомпилированной версии.

48
ответ дан Community 23 September 2019 в 13:31
поделиться

Если бы Вы собираетесь снова использовать регулярное выражение многократно, я создал бы его с RegexOptions.Compiled и кэшировал бы его. Нет никакого смысла в том, чтобы заставлять платформу проанализировать regex шаблон каждый раз, когда Вы хотите его.

31
ответ дан ewwink 23 September 2019 в 13:31
поделиться

Я соглашаюсь с Jon, и просто для уточнения это выглядело бы примерно так:

static Regex regex = new Regex("regex", RegexOptions.Compiled);

также worthwile для рассмотрения RegexOptions перечисление для других флагов, которые могут время от времени быть полезными.

8
ответ дан Andrew Hare 23 September 2019 в 13:31
поделиться

Для приложения WinForm я продолжал работать, мы могли определить regex на допустимых символах, которые будут работать на каждом нажатии клавиши и проверке для текста для любых текстовых полей (приложение ввода данных), таким образом, я использовал кэш или скомпилировал regexes такой как

  private static Dictionary<string, Regex> regexCache = new Dictionary<string, Regex>(20);

, Где regex выражение было ключом.

Тогда у меня была статическая функция, которую я мог вызвать при проверке данных:

public static bool RegExValidate(string text, string regex)
{
  if (!regexCache.ContainsKey(regex))
  {
    Regex compiledRegex = new Regex(regex,RegexOptions.Compiled);
    regexCache.Add(regex, compiledRegex);
  }
  return regexCache[regex].IsMatch(text);
}
2
ответ дан benPearce 23 September 2019 в 13:31
поделиться

Я предполагаю, что Вы читаете сообщение Jeff при компиляции Regex.

Что касается вопроса, если Вы задаете этот вопрос, это означает, что Вы собираетесь использовать его только однажды. Так, это действительно не имеет значения как дизассемблирование Отражателя Regex. IsMatch:

public static bool IsMatch(string input, string pattern, RegexOptions options)
{
    return new Regex(pattern, options, true).IsMatch(input);
}
3
ответ дан Recep 23 September 2019 в 13:31
поделиться

Есть много вещей, которые влияют на производительность при использовании регулярного выражения. В конечном счете, единственный способ определить наиболее эффективный в вашей ситуации - это измерить, используя как можно более реалистичную ситуацию.

На странице компиляции и повторного использования объектов регулярных выражений в MSDN это описано. Подводя итог, говорится, что

  1. Скомпилированные регулярные выражения требуют времени для компиляции, и после компиляции их память будет освобождена только при выгрузке AppDomain . Следует ли вам использовать компиляцию или нет, будет зависеть от количества используемых вами шаблонов и от того, как часто они используются.

  2. Статические Regex методы кэшируют проанализированное представление регулярного выражения для последних 15 (по умолчанию) узоры. Поэтому, если вы не используете много разных шаблонов в своем приложении, или ваше использование достаточно кластеризовано, не будет большой разницы между вы кэширующим экземпляр или фреймворком, кэширующим его.

6
ответ дан 26 November 2019 в 22:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: