C# 为什么正则表达式CompileToAssembly的性能比编译正则表达式和解释正则表达式慢?

C# 为什么正则表达式CompileToAssembly的性能比编译正则表达式和解释正则表达式慢?,c#,.net,regex,C#,.net,Regex,我使用以下代码对编译后的正则表达式测试CompileToAssembly性能,但结果不合适。请让我知道我错过了什么。谢谢 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)(.*)", RegexOptio

我使用以下代码对编译后的正则表达式测试CompileToAssembly性能,但结果不合适。请让我知道我错过了什么。谢谢

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);
    }

您的代码有一个问题:静态字段初始值设定项将在静态方法运行之前运行。这意味着在运行
Main()
之前,已经分配了
level4
。这意味着
level4
引用的对象不是在
CompileToAssembly()
中创建的类的实例

请注意,
Regex.CompileToAssembly
的示例代码显示了Regex的编译及其在两个不同程序中的使用。因此,您计时为“CompiledToAssembly”的实际正则表达式可能是您在早期测试中编译的不同正则表达式


另一个需要考虑的因素是:将程序集加载到内存并将其JIT到机器代码的开销可能非常大,您需要超过1000000次迭代才能看到好处。

您正在调试器(Visual Studio)下运行。它将防止在加载程序集时发生JIT优化。尝试在没有调试器的情况下运行(ctrl-f5)。

差别是55秒!这不是由于一次性加载开销造成的。看看我的答案。@usr,当然,这就是为什么我提到它是“另一个需要考虑的因素”。更重要的因素是OP的示例代码没有对预期的正则表达式计时。已经检查了将程序集加载到内存中的计时,与使用compileToAssembly选项时每次匹配所花费的时间相比,它可以忽略不计。另外,尝试在main()内创建对象,但没有效果。@user1322631是否检查了
match=level4.match(str)
是否产生了预期的结果?是,正则表达式是相同的,并给出相同的结果。如果不在没有调试器的情况下运行,将不会神奇地将
level4
string对象转换为已编译的正则表达式。正则表达式的汇编已在前面完成。。这里显示了我是如何将其编译成程序集的。这不是实际的代码。我尝试运行exe现在的结果更好。。。我不知道为什么我之前试过的时候会有奇怪的结果。新的结果仍然与理论不匹配以下是10000000次迭代的结果:RegexOption.Compiled:34413ms CompiledToAssembly:37125解释:47322。。。。为什么遵从汇编比编译正则表达式花费更多的时间?我只是自己运行代码。以下是我的结果:
RegexOptions.Compiled:8399ms
<代码>编译组件:7806ms<代码>已解释:10405ms。正如我所料。在Visual Studio中以调试模式再次尝试,得到大致相同的结果。您分别调用了
CompileToAssembly()
,然后运行该部件并注释掉,对吗?我现在尝试运行exe,结果更好。。。我不知道为什么我之前试过的时候会有奇怪的结果。新的结果仍然与理论不匹配以下是10000000次迭代的结果:RegexOption.Compiled:34413msCompiledToAssembly:37125解释:47322。。。。为什么编译汇编要比编译正则表达式花费更多的时间?我希望您在运行此程序时没有使用
CompileToAssembly(),否则将重新创建程序集,并且在调用
DuplicatedString
后必须再次进行JIT。从中我们了解到,重要的是程序集不是动态加载的,而是与项目静态链接的,即通过在预构建步骤中构建它。
RegexOptions.Compiled: 3908ms
CompiledToAssembly: 59349ms
Interpreted: 5653ms