0

我想要什么:我必须查看并证明简单的正则表达式运行速度是否比编译的慢。我决定生成 100000 个随机字符串,制作两个正则表达式——一个简单,一个编译——并检查这 100000 个字符串集中的匹配项。此外,为了解决许多输出问题,我最初所做的是获取所有 100000 个字符串并运行代码并记录时间,然后我从同一组中获取前 80000 个字符串并记录输出,然后我获取前 50000 个字符串来自同一组并记录输出等等......

编码:

var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var random = new Random();
int[] reps = new int[] { 1,10,100,1000,2000,5000,8000,10000,20000,50000,80000,100000 };

List<string> strings = new List<string>();
// generating random strings
for (int i = 0; i < reps[reps.Length-1]; i++)
     strings.Add(new string(
                    Enumerable.Repeat(chars, 8)
                              .Select(s => s[random.Next(s.Length)])
                              .ToArray()));

String regexStr = "[AEIOU]{2,3}(QWERTY|ASDFGH|ZXCVBN){}";
Regex regexSimple = new Regex(regexStr);
Regex regexCompiled = new Regex(regexStr, RegexOptions.Compiled);

using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Users\harshittiwari\Desktop\Assignment1\test2.txt"))
{
       file.WriteLine("numberOfStrings,ticksForSimpleRegex,ticksForComplexRegex");

       List<long> simple = new List<long>();
       List<long> compiled = new List<long>();
       for (int j = reps.Length - 1; j >= 0; j--)
       {
             Stopwatch time1 = Stopwatch.StartNew();
             for (int k = 0; k < reps[j]; k++)
                  regexSimple.Matches(strings[k]);
             time1.Stop();
             simple.Add(time1.ElapsedTicks);
       }

       for (int j = reps.Length - 1; j >= 0; j--)
       {
                    Stopwatch time1 = Stopwatch.StartNew();
                    for (int k = 0; k < reps[j]; k++)
                        regexCompiled.Matches(strings[k]);
                    time1.Stop();
                    compiled.Add(time1.ElapsedTicks);
       }

       for (int j = reps.Length - 1,k=0; j >= 0; j--,k++)
            file.WriteLine(reps[j] + "," + simple[k] + "," + compiled[k]);
}

问题:我得到了一些难以解释的奇怪输出。输出是:

numberOfStrings,ticksForSimpleRegex,ticksForComplexRegex
100000,300368,217506
80000,240373,201553
50000,178212,98878
20000,13362,202933
10000,6417,6377
8000,5868,7408
5000,3737,3142
2000,160473,1921
1000,1351,1883
100,84,141
10,23,21
1,17,17

请注意,numberOfStrings=2000 的 ticksForSimpleRegex 明显大于 numberOfStrings=5000 的 ticksForSimpleRegex。每次我运行程序时,它或多或少都是一样的。是因为一些缓存问题还是由于编译器优化?另外,我应该怎么做才能使输出保持一致?一致我的意思是 ticksForSimpleRegex 应该按降序排列(基本逻辑:字符串数量减少,所用时间减少。)

在这里我还想说,最初我阅读的字符串数量较少,然后又要阅读更多数量的字符串,例如:

1,..,..
10,..,..
100,..,..
1000,..,..
...
80000,..,..
100000,..,..

但是,我意识到了一些缓存问题,并决定按照现在的顺序进行。

EDIT1:我读了http://allben.net/post/2009/08/06/Performance-Compiled-vs-Interpreted-Regular-Expressions他们说解释(简单)正则表达式应该花费更少的时间,但是在我们的例子中,这不是结果。为什么会这样?

4

2 回答 2

2

当使用IsMatch()方法而不是 时Matches(),代码不会创建大量需要收集的对象(并且可能在您看到性能命中时被收集)。通过这种方式,我似乎得到了相当一致的结果。

于 2013-08-16T10:11:49.650 回答
1

除了 C.Evenhuis 的回答之外,我得到了我的回答,关于为什么垃圾收集器每次都会以 2000 或 1000 的速度启动。原因是对象和对象的大小保持不变,匹配和正则表达式,堆大小保持不变。这就是垃圾收集器只在那个时候被填满的原因。如果我更改随机字符串的大小,那么这可能会有所不同。

对 EDIT1 的回答是,在提到的基准测试中,有 5000 种不同的正则表达式和用于编译和解释的基准测试。我们正在使用 1 个正则表达式。话虽这么说,很明显,如果您有很多正则表达式,最好使用解释的正则表达式。如果您有一个简单的正则表达式并且必须在许多字符串上对其进行测试,请使用已编译的正则表达式

于 2013-08-16T10:48:23.060 回答