这只是一个满足我好奇心的问题.但对我来说这很有意思.
我写了这个简单的小基准.它以随机顺序调用3个Regexp执行变体几千次:
基本上,我使用相同的模式,但以不同的方式.
没有任何你的普通方式RegexOptions
.从.NET 2.0开始,这些不会被缓存.但是应该"缓存",因为它保存在一个非常全局的范围内而不是重置.
同 RegexOptions.Compiled
调用静态Regex.Match(pattern, input)
,它在.NET 2.0中得到缓存
这是代码:
static ListStrings = new List (); 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
这几乎也淘汰了所有其他问题.
谢谢你的回答.