为什么 regex.IsMatch(str) 比 str.EndsWith(不变文化)快?
Why is regex.IsMatch(str) faster than str.EndsWith (invariant culture)?
这是针对每纳秒遍历无数次并且需要快速的代码路径的一些微基准测试。
对于下面的代码片段,比较
x.EndsWith(y, InvariantCulture)
Regex(y, Compiled | CultureInvariant).IsMatch(x)
我得到以下数字:
=============================
Regex : 00:00:01.2235890. Ignore this: 16666666
EndsWith: 00:00:03.2194626. Ignore this: 16666666
=============================
Regex : 00:00:01.0979105. Ignore this: 16666666
EndsWith: 00:00:03.2346031. Ignore this: 16666666
=============================
Regex : 00:00:01.0687845. Ignore this: 16666666
EndsWith: 00:00:03.3199213. Ignore this: 16666666
换句话说,EndsWith
需要的时间是Regex
的3倍。
我应该注意,我尝试了其他值,取决于所使用的字符串值,有时 EndsWith
更快,有时 Regex
是 。
EndsWith(x, InvariantCulture)
归结为一些参数检查,然后 extern int nativeCompareOrdinalEx(String, int, String, int, int)
,我希望它很快 。 (正如@nhahtdh 正确指出的那样,在 InvariantCulture
的情况下,它调用 CultureInfo.InvariantCulture.CompareInfo.IsSuffix which calls InternalFindNLSStringEx
。我不小心遵循了 Ordinal
路径)
N.B.:我刚刚发现当使用 Ordinal
而不是 InvariantCulture
调用 EndsWith 时,EndsWith 比 InvariantCulture
快得多正则表达式...不幸的是,没有 RegexOptions.Ordinal
可以与之进行比较。
我也期望编译后的正则表达式很快,但是它怎么能打败专门的方法呢?
乐码:
string[] BunchOfIDs =
{
"zxc@x@432143214@O@abcße",
"zxc@x@432143214@T@abcßX",
"qwe@x@432143214@O@abcße",
"qwe@x@432143214@XXabc",
"zxc@x@1234@O@aXcße",
"qwe@y@1234@O@aYcße",
};
var endsWith = "@abcße";
var endsWithRegex = new Regex("@abcße$", RegexOptions.None);
int reps = 20000000;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("=============================");
int x = 0;
var sw = Stopwatch.StartNew();
for (int j = 0; j < reps; j++)
{
x += BunchOfIDs[j % BunchOfIDs.Length].EndsWith(endsWith, StringComparison.InvariantCulture) ? 1 : 2;
}
Console.WriteLine("EndsWith: " + sw.Elapsed + ". Ignore this: " + x);
x = 0;
sw = Stopwatch.StartNew();
for (int j = 0; j < reps; j++)
{
x += endsWithRegex.IsMatch(BunchOfIDs[j % BunchOfIDs.Length]) ? 1 : 2;
}
Console.WriteLine("Regex : " + sw.Elapsed + ". Ignore this: " + x);
}
可能是
因为StringComparison.InvariantCulture != RegexOptions.CultureInvariant
!
这个片段
var str = "ss";
var endsWith = "ß";
var endsWithRegex = new Regex("ß$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
Console.WriteLine(str.EndsWith(endsWith, StringComparison.InvariantCulture)
+ " vs "
+ endsWithRegex.IsMatch(str));
打印
True vs False
所以看起来 RegexOptions.CultureInvariant 并不暗示 StringComparison.InvariantCulture 所暗示的东西。 RegexOptions.CultureInvariant 是否更像 StringComparison.Ordinal?
这是针对每纳秒遍历无数次并且需要快速的代码路径的一些微基准测试。
对于下面的代码片段,比较
x.EndsWith(y, InvariantCulture)
Regex(y, Compiled | CultureInvariant).IsMatch(x)
我得到以下数字:
=============================
Regex : 00:00:01.2235890. Ignore this: 16666666
EndsWith: 00:00:03.2194626. Ignore this: 16666666
=============================
Regex : 00:00:01.0979105. Ignore this: 16666666
EndsWith: 00:00:03.2346031. Ignore this: 16666666
=============================
Regex : 00:00:01.0687845. Ignore this: 16666666
EndsWith: 00:00:03.3199213. Ignore this: 16666666
换句话说,EndsWith
需要的时间是Regex
的3倍。
我应该注意,我尝试了其他值,取决于所使用的字符串值,有时 EndsWith
更快,有时 Regex
是 。
EndsWith(x, InvariantCulture)
归结为一些参数检查,然后 。 (正如@nhahtdh 正确指出的那样,在 extern int nativeCompareOrdinalEx(String, int, String, int, int)
,我希望它很快 InvariantCulture
的情况下,它调用 CultureInfo.InvariantCulture.CompareInfo.IsSuffix which calls InternalFindNLSStringEx
。我不小心遵循了 Ordinal
路径)
N.B.:我刚刚发现当使用 Ordinal
而不是 InvariantCulture
调用 EndsWith 时,EndsWith 比 InvariantCulture
快得多正则表达式...不幸的是,没有 RegexOptions.Ordinal
可以与之进行比较。
我也期望编译后的正则表达式很快,但是它怎么能打败专门的方法呢?
乐码:
string[] BunchOfIDs =
{
"zxc@x@432143214@O@abcße",
"zxc@x@432143214@T@abcßX",
"qwe@x@432143214@O@abcße",
"qwe@x@432143214@XXabc",
"zxc@x@1234@O@aXcße",
"qwe@y@1234@O@aYcße",
};
var endsWith = "@abcße";
var endsWithRegex = new Regex("@abcße$", RegexOptions.None);
int reps = 20000000;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("=============================");
int x = 0;
var sw = Stopwatch.StartNew();
for (int j = 0; j < reps; j++)
{
x += BunchOfIDs[j % BunchOfIDs.Length].EndsWith(endsWith, StringComparison.InvariantCulture) ? 1 : 2;
}
Console.WriteLine("EndsWith: " + sw.Elapsed + ". Ignore this: " + x);
x = 0;
sw = Stopwatch.StartNew();
for (int j = 0; j < reps; j++)
{
x += endsWithRegex.IsMatch(BunchOfIDs[j % BunchOfIDs.Length]) ? 1 : 2;
}
Console.WriteLine("Regex : " + sw.Elapsed + ". Ignore this: " + x);
}
可能是
因为StringComparison.InvariantCulture != RegexOptions.CultureInvariant
!
这个片段
var str = "ss";
var endsWith = "ß";
var endsWithRegex = new Regex("ß$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
Console.WriteLine(str.EndsWith(endsWith, StringComparison.InvariantCulture)
+ " vs "
+ endsWithRegex.IsMatch(str));
打印
True vs False
所以看起来 RegexOptions.CultureInvariant 并不暗示 StringComparison.InvariantCulture 所暗示的东西。 RegexOptions.CultureInvariant 是否更像 StringComparison.Ordinal?