Dot-Net

為什麼 regex.IsMatch(str) 比 str.EndsWith (不變文化)快?

  • January 18, 2015

這是對每納秒遍歷無數次並且需要快速的程式碼路徑的一些微基準測試。

對於下面的程式碼片段,比較

  • 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需要 3 倍的時間Regex

我應該注意,我嘗試了其他值,並且根據使用的字元串值,有時EndsWith更快,有時Regex.

EndsWith(x, InvariantCulture)歸結為一些參數檢查然後extern int nativeCompareOrdinalEx(String, int, String, int, int),我希望它很快。(正如@nhahtdh 正確指出的那樣,在InvariantCulture它呼叫的情況下CultureInfo.InvariantCulture.CompareInfo.IsSuffix which calls InternalFindNLSStringEx。我不小心跟踪了Ordinal線索)

注意:我剛剛發現當用Ordinal而不是呼叫 EndsWith 時InvariantCulture,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);
}

有可能

因為**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 嗎?

引用自:https://stackoverflow.com/questions/27958053