1

我有两个文本框,一个用于输入,另一个用于输出。我只需要从输入中过滤十六进制字符并以大写形式输出。我检查过使用正则表达式 ( Regex) 比使用循环快得多。

我当前的代码首先变为大写,然后过滤十六进制数字,如下所示:

string strOut = Regex.Replace(inputTextBox.Text.ToUpper(), "[^0-9^A-F]", "");
outputTextBox.Text = strOut;

另一种选择:

string strOut = Regex.Replace(inputTextBox.Text, "[^0-9^A-F^a-f]", "");
outputTextBox.Text = strOut.ToUpper();

输入最多可以包含 32k 个字符,因此速度在这里很重要。我曾经TimeSpan测量过,但结果并不一致。

我的问题是:哪个代码具有更好的速度性能,为什么?

4

3 回答 3

3

这绝对是一个过早优化的例子:32K 个字符对于在现代计算机上运行的经过微调的正则表达式引擎来说并不是什么大问题,所以这个优化任务主要是理论上的。

在讨论性能之前,值得指出的是表达式可能没有按照您的意愿执行,因为它们允许^字符进入输出。您需要使用[^0-9A-F]and[^0-9A-Fa-f]来代替。

两个正则表达式的速度将相同,因为字符类中的字符数几乎没有区别。但是,第二个组合ToUpper调用将在可能更短的字符串上调用,因为所有无效字符都将被删除。因此,第二种选择可能会稍微快一些。

但是,如果您必须将其优化到最后一个 CPU 周期,您可以在不使用正则表达式的情况下重写它,以避免在ToUpper: 循环中遍历输入字符串,并随时添加所有有效字符StringBuilder。当您看到一个小写字符时,将其转换为大写。

于 2013-05-29T01:05:36.073 回答
1

测试很简单:

using System;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string letters = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ";
            Random random = new Random();
            string[] strings = Enumerable.Range(0, 5000).Select(i1 => string.Join("", Enumerable.Range(0,32000).Select(i2 => letters[random.Next(0, letters.Length - 1)]))).ToArray();

            Stopwatch stopwatchA = new Stopwatch();
            stopwatchA.Start();

            foreach (string s in strings)
                Regex.Replace(s.ToUpper(), "[^0-9^A-F]", "");

            stopwatchA.Stop();

            Stopwatch stopwatchB = new Stopwatch();
            stopwatchB.Start();

            foreach (string s in strings)
                Regex.Replace(s, "[^0-9^A-F^a-f]", "").ToUpper();

            stopwatchB.Stop();

            Debug.WriteLine("stopwatchA: {0}", stopwatchA.Elapsed);
            Debug.WriteLine("stopwatchB: {0}", stopwatchB.Elapsed);
        }
    }
}

运行 1:

秒表A: 00:00:39.6552012

秒表B:00:00:40.6757048

运行 2:

秒表A: 00:00:39.7022437

秒表B:00:00:41.3477625

在那些运行中,第一种方法更快。

于 2013-05-29T01:18:56.860 回答
0

在理论大小上,string.ToUpper()可以潜在地分配一个新字符串(请记住,.NET 字符串在语义上是不可变的),但另一方面,正则表达式可以节省内存,即在一般情况下它应该更快(对于大字符串)。toUpper()如果使用调用,输入字符串也将循环两次。

于 2013-12-08T09:03:57.203 回答