Вопрос по .net, regex, c# – Почему Regex CompileToAssembly дает более медленную производительность, чем скомпилированные регулярные выражения и интерпретированные регулярные выражения?

7

Я использую следующий код для проверки производительности CompileToAssembly против скомпилированного регулярного выражения, но результаты не соответствуют. Пожалуйста, дайте мне знать, что мне не хватает. Спасибо!!!

<code>static readonly Regex regex = new Regex(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)", RegexOptions.Compiled);
static readonly Regex reg = new Regex(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)");
static readonly Regex level4 = new DuplicatedString();

    static void Main()
    {
        const string str = "add time 243,3453,43543,543,534534,54534543,345345,4354354235,345435,34543534 6873brekgnfkjerkgiengklewrij";
        const int itr = 1000000;
        CompileToAssembly();
        Match match;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < itr; i++)
        {
             match = regex.Match(str);
        }
        sw.Stop();
        Console.WriteLine("RegexOptions.Compiled: {0}ms", sw.ElapsedMilliseconds);

        sw.Reset();
        sw.Start();
        for (int i = 0; i < itr; i++)
        {
            match = level4.Match(str);
        }
        sw.Stop();

        Console.WriteLine("CompiledToAssembly: {0}ms", sw.ElapsedMilliseconds);

        sw.Reset();
        sw.Start();
        for (int i = 0; i < itr; i++)
        {
            match = reg.Match(str);
        }
        sw.Stop();
        Console.WriteLine("Interpreted: {0}ms", sw.ElapsedMilliseconds);
        Console.ReadLine();
    }

    public static void CompileToAssembly()
    {
        RegexCompilationInfo expr;
        List<RegexCompilationInfo> compilationList = new List<RegexCompilationInfo>();

        // Define regular expression to detect duplicate words
        expr = new RegexCompilationInfo(@"(stats|pause\s?(all|\d+(\,\d+)*)|start\s?(all|\d+(\,\d+)*)|add\s?time\s?(all|\d+(\,\d+)*)(\s\d+)|c(?:hange)?\s?p(?:asskey)?|close)(.*)",
                   RegexOptions.Compiled,
                   "DuplicatedString",
                   "Utilities.RegularExpressions",
                   true);
        // Add info object to list of objects
        compilationList.Add(expr);

        // Apply AssemblyTitle attribute to the new assembly
        //
        // Define the parameter(s) of the AssemblyTitle attribute's constructor 
        Type[] parameters = { typeof(string) };
        // Define the assembly's title
        object[] paramValues = { "General-purpose library of compiled regular expressions" };
        // Get the ConstructorInfo object representing the attribute's constructor
        ConstructorInfo ctor = typeof(System.Reflection.AssemblyTitleAttribute).GetConstructor(parameters);
        // Create the CustomAttributeBuilder object array
        CustomAttributeBuilder[] attBuilder = { new CustomAttributeBuilder(ctor, paramValues) };

        // Generate assembly with compiled regular expressions
        RegexCompilationInfo[] compilationArray = new RegexCompilationInfo[compilationList.Count];
        AssemblyName assemName = new AssemblyName("RegexLib, Version=1.0.0.1001, Culture=neutral, PublicKeyToken=null");
        compilationList.CopyTo(compilationArray);
        Regex.CompileToAssembly(compilationArray, assemName, attBuilder);
    }
</code>

Ниже приведены результаты:

<code>RegexOptions.Compiled: 3908ms
CompiledToAssembly: 59349ms
Interpreted: 5653ms
</code>
Я просто запустил код сам. Вот мои результаты:RegexOptions.Compiled: 8399ms; CompiledToAssembly: 7806ms; Interpreted: 10405ms, Как раз то, что я ожидал. mellamokb
Попробовал еще раз в Visual Studio в режиме отладки, получил примерно те же результаты. Ты звонишьCompileToAssembly() отдельно, затем работает с этой частью закомментировано, правильно? mellamokb
Я попытался запустить exe, теперь результаты лучше ... Не знаю, почему он давал странные результаты, когда я пытался сделать это раньше. Тем не менее, результаты не совпадают с теорией. Ниже приведены результаты для 10000000 итераций: RegexOption.Compiled: 34413msCompiledToAssembly: 37125 Интерпретировано: 47322 .... Почему соответствие сборке заняло больше времени, чем скомпилированное регулярное выражение ?? iRock
Я надеюсь, что вы запустили это без линииCompileToAssembly();в противном случае сборка будет воссоздана и должна быть снова подключена после вызоваDuplicatedString, ОтBest Practices мы узнаем, что важно, чтобы сборкаnot динамически загружается, но статически связан с вашим проектом, т. е. собирается на этапе предварительной сборки. Abel

Ваш Ответ

2   ответа
6

будут запускаться инициализаторы статического поляbefore статические методы запускаются. Это означает, чтоlevel4 уже был назначен ранееMain() пробеги. Это означает, что объект, на который ссылаетсяlevel4 являетсяnot экземпляр класса, созданный вCompileToAssembly().

Обратите внимание, что пример кода дляRegex.CompileToAssembly показывает компиляцию регулярного выражения и его потребление вtwo different programs.  Фактическое регулярное выражение, которое вы указали как «CompiledToAssembly» следовательно, это может быть другое регулярное выражение, которое вы скомпилировали в предыдущем тесте.

Еще один фактор, который необходимо учитывать: издержки загрузки сборки в память и ее привязки к машинному коду могут быть достаточно значительными, чтобы вам потребовалось более 1 000 000 итераций, чтобы увидеть преимущество.

Разница 55 с! Это не связано с разовой загрузкой. Смотри мой ответ.
@usr, конечно, поэтому я упомянул это как «еще один фактор, который нужно учитывать». Более важным фактором является то, что пример кода OPis not timing the intended regex.
Уже проверено время загрузки сборки в память, оно ничтожно мало по сравнению со временем, затрачиваемым на каждое совпадение при использовании параметра compileToAssembly. Также попытался создать объект внутри main () без эффекта как такового. iRock
@ user1322631 ты проверял этоmatch = level4.Match(str) дает ожидаемый результат?
Да, регулярное выражение такое же и дает те же результаты. iRock
4

мизацию при загрузке сборки. Попробуйте запустить без отладчика (Ctrl-F5).

Я попытался запустить exe, теперь результаты лучше ... Не знаю, почему он давал странные результаты, когда я пытался сделать это раньше. Тем не менее, результаты не совпадают с theroy. Ниже приведены результаты для 10000000 итераций: RegexOption.Compiled: 34413ms CompiledToAssembly: 37125 Интерпретировано: 47322 .... Почему соблюдение сборки заняло больше времени, чем скомпилированное регулярное выражение ?? iRock
Компиляция в сборку для регулярного выражения была сделана ранее ... показано здесь, как я собрал его в сборку. Это не фактический код. iRock
Пробовал, что уже не так много улучшений :( iRock
Не работает без отладчика не будет волшебным образом повернутьlevel4 строковый объект в скомпилированное регулярное выражение.

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