C# 哪个正则表达式和toUpper组合更快?
我有两个文本框,一个用于输入,另一个用于输出。我只需要从输入中过滤十六进制字符,然后以大写形式输出。我已经检查过使用正则表达式(C# 哪个正则表达式和toUpper组合更快?,c#,regex,hex,toupper,C#,Regex,Hex,Toupper,我有两个文本框,一个用于输入,另一个用于输出。我只需要从输入中过滤十六进制字符,然后以大写形式输出。我已经检查过使用正则表达式(Regex)比使用循环快得多 首先将我的当前代码转换为大写,然后过滤十六进制数字,如下所示: string strOut = Regex.Replace(inputTextBox.Text.ToUpper(), "[^0-9^A-F]", ""); outputTextBox.Text = strOut; 或者: string strOut = Regex.Repla
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
进行测量,但结果不一致
我的问题是:哪种代码具有更好的速度性能以及原因?这肯定是过早优化的情况:32K字符对于在现代计算机上运行的经过微调的正则表达式引擎来说并不是什么大问题,因此此优化任务主要是理论性的 在讨论性能之前,值得指出的是,表达式可能没有达到您想要的效果,因为它们允许
^
字符进入输出。您需要使用[^0-9A-F]
和[^0-9A-Fa-F]
两个正则表达式的速度是相同的,因为字符类中的字符数几乎没有区别。但是,第二个组合ToUpper
调用将在可能较短的字符串上调用,因为所有无效字符都将被删除。因此,第二种选择可能会稍微快一点
但是,如果必须将其优化到最后一个CPU周期,则可以在不使用正则表达式的情况下重写它,以避免
ToUpper
中的内存分配:在循环中遍历输入字符串,并将所有有效字符添加到StringBuilder
。当您看到小写字符时,请将其转换为大写。这肯定是过早优化的情况:32K字符对于在现代计算机上运行的经过微调的正则表达式引擎来说不是什么大问题,因此此优化任务主要是理论性的
在讨论性能之前,值得指出的是,表达式可能没有达到您想要的效果,因为它们允许^
字符进入输出。您需要使用[^0-9A-F]
和[^0-9A-Fa-F]
两个正则表达式的速度是相同的,因为字符类中的字符数几乎没有区别。但是,第二个组合ToUpper
调用将在可能较短的字符串上调用,因为所有无效字符都将被删除。因此,第二种选择可能会稍微快一点
但是,如果必须将其优化到最后一个CPU周期,则可以在不使用正则表达式的情况下重写它,以避免ToUpper
中的内存分配:在循环中遍历输入字符串,并将所有有效字符添加到StringBuilder
。当您看到小写字符时,请将其转换为大写。测试很简单:
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
在那些to运行中,第一种方法更快。测试很简单:
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
在那些要运行的程序中,第一种方法更快。在理论大小上,
string.ToUpper()
可以潜在地分配一个新字符串(请记住,.NET字符串在语义上是不可变的),但正则表达式另一方面可以节省内存,即在一般情况下(对于大字符串),它应该更快。此外,如果使用toUpper()
调用,输入字符串将循环两次。在理论大小上,string.toUpper()
可能会分配一个新字符串(请记住,.NET字符串在语义上是不可变的),但正则表达式另一方面可以节省内存,也就是说,在一般情况下(对于大字符串),它应该更快。此外,如果使用toUpper()
调用,输入字符串将循环两次。您确定这不是过早优化的情况吗?您是否希望文本框每秒填充32K字符超过1000次?您确定这不是过早优化的情况吗?您是否希望文本框每秒填充32K个字符超过1000次?“字符类中的字符数几乎不起作用”请阅读,整个原因\d
比[0-9]慢
是因为它包含了更多的字符。@AJMansfield这不是因为\d
只是包含了更多的字符,而是因为代码点太分散了。但是,在本例中,字符彼此相邻,因此额外检查小写字符不会花费太多时间。好的,我明白你的意思。此外,如果您真的需要对其进行优化,您应该针对GPU而不是标准CPU对其进行优化。“字符类中的字符数几乎没有什么区别”请阅读,原因是\d
比[0-9]慢
是因为它包含了更多的字符。@AJMansfield这不是因为\d
只是包含了更多的字符,而是因为代码点太分散了。但是,在本例中,字符彼此相邻,因此额外检查小写字符不会花费太多时间。好的,我明白你的意思。另外,如果你真的需要优化它,你应该针对GPU而不是标准CPU来优化它。这不是一个好的基准测试,因为没有任何东西会被丢弃:两个表达式都会传递所有信息。您需要在混合中添加相当数量的非字母,然后看看这两个表达式是如何表达的