這只是一個問題,以滿足我的好奇心。 但對我來說這很有趣。爲什麼緩存的Regexp超越編譯好的版本?
我寫了這個簡單的基準。它以幾千次的隨機順序調用Regexp執行的3個變體:
基本上,我使用相同的模式,但以不同的方式。
您的普通方式沒有任何
RegexOptions
。從.NET 2.0開始,這些不會被緩存。但應該「緩存」,因爲它保存在一個非常全球的範圍內,而不是重置。隨着
RegexOptions.Compiled
隨着到靜態
Regex.Match(pattern, input)
調用它不會在.NET 2.0
這裏獲取緩存是代碼:
static List<string> Strings = new List<string>();
static string pattern = ".*_([0-9]+)\\.([^\\.])$";
static Regex Rex = new Regex(pattern);
static Regex RexCompiled = new Regex(pattern, RegexOptions.Compiled);
static Random Rand = new Random(123);
static Stopwatch S1 = new Stopwatch();
static Stopwatch S2 = new Stopwatch();
static Stopwatch S3 = new Stopwatch();
static void Main()
{
int k = 0;
int c = 0;
int c1 = 0;
int c2 = 0;
int c3 = 0;
for (int i = 0; i < 50; i++)
{
Strings.Add("file_" + Rand.Next().ToString() + ".ext");
}
int m = 10000;
for (int j = 0; j < m; j++)
{
c = Rand.Next(1, 4);
if (c == 1)
{
c1++;
k = 0;
S1.Start();
foreach (var item in Strings)
{
var m1 = Rex.Match(item);
if (m1.Success) { k++; };
}
S1.Stop();
}
else if (c == 2)
{
c2++;
k = 0;
S2.Start();
foreach (var item in Strings)
{
var m2 = RexCompiled.Match(item);
if (m2.Success) { k++; };
}
S2.Stop();
}
else if (c == 3)
{
c3++;
k = 0;
S3.Start();
foreach (var item in Strings)
{
var m3 = Regex.Match(item, pattern);
if (m3.Success) { k++; };
}
S3.Stop();
}
}
Console.WriteLine("c: {0}", c1);
Console.WriteLine("Total milliseconds: " + (S1.Elapsed.TotalMilliseconds).ToString());
Console.WriteLine("Adjusted milliseconds: " + (S1.Elapsed.TotalMilliseconds).ToString());
Console.WriteLine("c: {0}", c2);
Console.WriteLine("Total milliseconds: " + (S2.Elapsed.TotalMilliseconds).ToString());
Console.WriteLine("Adjusted milliseconds: " + (S2.Elapsed.TotalMilliseconds*((float)c2/(float)c1)).ToString());
Console.WriteLine("c: {0}", c3);
Console.WriteLine("Total milliseconds: " + (S3.Elapsed.TotalMilliseconds).ToString());
Console.WriteLine("Adjusted milliseconds: " + (S3.Elapsed.TotalMilliseconds*((float)c3/(float)c1)).ToString());
}
每次我叫它結果如下:
Not compiled and not automatically cached: Total milliseconds: 6185,2704 Adjusted milliseconds: 6185,2704 Compiled and not automatically cached: Total milliseconds: 2562,2519 Adjusted milliseconds: 2551,56949184038 Not compiled and automatically cached: Total milliseconds: 2378,823 Adjusted milliseconds: 2336,3187176891
所以你有它。不多,但約7-8%的差異。
這不是唯一的祕密。我無法解釋爲什麼第一種方法會慢得多,因爲它不會被重新評估,而是被保存在一個全局靜態變量中。
順便說一句,這是在.net 3.5和Mono 2.2上表現完全一樣。在Windows上。
那麼,任何想法,爲什麼編譯的變體甚至會落後?
EDIT1:
Not compiled and not automatically cached: Total milliseconds: 6456,5711 Adjusted milliseconds: 6456,5711 Compiled and not automatically cached: Total milliseconds: 2668,9028 Adjusted milliseconds: 2657,77574842168 Not compiled and automatically cached: Total milliseconds: 6637,5472 Adjusted milliseconds: 6518,94897724836
還幾乎廢止所有的其他問題還有:
固定碼結果現在這個樣子了。
感謝您的答案。
謝謝你的解釋。 在我的情況下,最初的步驟似乎不會導致很多成本(請參閱新結果)。 我在發佈之前閱讀了Jeff Atwood的帖子。所以我知道這些缺點。在我的情況下,編譯選項會有所幫助,雖然在標準用例中沒有那麼多。 – user51710 2009-01-09 15:15:52
** Jeff Atwood的帖子已經移到:[編譯或不編譯*(2005年3月3日)*](http://blog.codinghorror.com/to-compile-or-not-to-compile/) – DavidRR 2014-04-10 17:39:43