【发布时间】:2015-01-15 06:44:49
【问题描述】:
这是针对每纳秒遍历数亿次且需要快速的代码路径的一些微基准测试。
对于下面的代码sn-p,比较
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 线索)
注意:我刚刚发现,当使用 Ordinal 而不是 InvariantCulture 调用 EndsWith 时,EndsWith 比正则表达式快得多......不幸的是,没有 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);
}
【问题讨论】:
-
EndsWith(x, InvariantCulture) boils down to some argument checking and then extern int nativeCompareOrdinalEx(String, int, String, int, int), which I'd expect to be fast.你用 InvariantCulture 调用了 EndsWith,所以它不应该调用CultureInfo.InvariantCulture.CompareInfo.IsSuffix来调用InternalFindNLSStringEx吗? referencesource.microsoft.com/#mscorlib/system/… -
@nhahtdh 你是对的。将仔细检查并更新。
-
当您将代表次数增加 10 倍时,差异会变得不那么明显(结束:21 秒与正则表达式:17 秒 - 远低于运行次数较少时的 2-3 倍加速)。也许 JIT 对热代码路径进行了更重的优化(Safari 的 JS 解释器这样做是为了优化启动速度)。另一方面,编译的正则表达式从一开始就进行大量优化是有意义的。
标签: .net regex string performance