我有以下代码:
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使用方:
我有filed an issue for .NET Core和fixed it with a PR。
如果您需要将其合并回常规的.NET Framework,则应在github上提交问题以请求反向移植。
该问题针对已设置的所有已编译正则表达式显示
RegexOptions.Compiled
看似奇怪的选项RegexOptions.CultureInvariant |如果在具有特定语言环境的线程上创建正则表达式,则该表达式实际上是必需的,该语言环境具有特殊的大小写或数字分隔符。正则表达式匹配表达式将根据您当前的语言环境专门创建。如果要使用与区域设置无关的正则表达式,则需要使用RegexOptions.CultureInvariant。
关于c# - 为什么C#RegexOptions.Compiled会使匹配变慢?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40953573/