我有以下代码:

static void Main(string[] args)
{
    const string RegXPattern = @"/api/(?<controller>\w+)/(?<action>\w+)/?$";
    var regex = new Regex(RegXPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);

    const string InputToMatch = "/api/person/load";

    regex.IsMatch(InputToMatch); // Warmup

    var sw = Stopwatch.StartNew();
    for (int i = 0; i < 10000000; i++)
    {
        var match = regex.IsMatch(InputToMatch);
    }
    sw.Stop();

    Console.WriteLine(sw.Elapsed.ToString());
    Console.ReadLine();
}

在Releae下在我的计算机上运行以上命令,大约需要 18 秒才能完成,删除RegexOptions.Compiled使其可以在 13 秒内运行。

我的理解是,包括此标志会使匹配速度更快,但在我的示例中,这将导致性能降低约30%。

我在这里想念什么?

最佳答案

问题在于,已编译的Regex版本会与当前表格的区域性进行逐个字符比较

if .... char.ToLower(runtext[index2], CultureInfo.CurrentCulture) == 'c' ....

对于每个字符,在哪里检索线程静态CultureInfo.CurrentCulture。

这在事件探查器中显示为CPU使用方:

c# - 为什么C#RegexOptions.Compiled会使匹配变慢?-LMLPHP

我有filed an issue for .NET Corefixed it with a PR
如果您需要将其合并回常规的.NET Framework,则应在github上提交问题以请求反向移植。
该问题针对已设置的所有已编译正则表达式显示
  • RegexOptions.IgnoreCase | RegexOptions.Compiled
  • RegexOptions.CultureInvariant | RegexOptions.Compiled
  • RegexOptions.CultureInvariant | RegexOptions.IgnoreCase
    RegexOptions.Compiled

  • 看似奇怪的选项RegexOptions.CultureInvariant |如果在具有特定语言环境的线程上创建正则表达式,则该表达式实际上是必需的,该语言环境具有特殊的大小写或数字分隔符。正则表达式匹配表达式将根据您当前的语言环境专门创建。如果要使用与区域设置无关的正则表达式,则需要使用RegexOptions.CultureInvariant。

    关于c# - 为什么C#RegexOptions.Compiled会使匹配变慢?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40953573/

    10-09 21:41