在字符串上使用LINQ的性能
本文关键字:LINQ 性能 字符串 | 更新日期: 2023-09-27 18:18:24
我做了两个测试,因为我想测试在两个不同的实现上尝试在字符串中找到一个数字的性能。
这是我的代码:
[TestMethod]
public void TestMethod1()
{
string text = "I want to find the number (30)";
var startNumber = text.IndexOf('(');
var trimmed = text.Trim(')');
var number = trimmed.Substring(startNumber).Trim('(');
Assert.AreEqual("30", number);
}
[TestMethod]
public void TestMethod2()
{
string text = "I want to find the number (30)";
var lambdaNumber = text.Where(x => Char.IsNumber(x)).ToArray();
var joined = string.Join("", lambdaNumber);
Assert.AreEqual("30", joined);
}
结果是TestMethod2(带lambda表达式)比TestMethod1快。根据测试浏览器。
TestMethod1 = 2msTestMethod2 = <1ms
如果我尝试在每个测试中添加StopWatch, TestMethod1是迄今为止最快的。
如何正确地测试此行为的性能?
编辑:我欣赏这两个方法不执行相同操作的事实。因此,我创建了以下代码:
[TestMethod]
public void TestMethod1()
{
var sw = new Stopwatch();
sw.Start();
var number = string.Empty;
var counter = 0;
while (counter < 100000)
{
number = string.Empty;
string text = "I want to find the number (30)";
foreach (var c in text.ToCharArray())
{
int outNumber;
if (int.TryParse(c.ToString(), out outNumber))
number += c.ToString();
}
counter++;
}
sw.Stop();
Assert.AreEqual("30", number);
}
[TestMethod]
public void TestMethod2()
{
var sw = new Stopwatch();
sw.Start();
var joined = String.Empty;
var counter = 0;
while (counter < 100000)
{
string text = "I want to find the number (30)";
var lambdaNumber = text.Where(x => Char.IsNumber(x)).ToArray();
joined = string.Join("", lambdaNumber);
counter++;
}
sw.Stop();
Assert.AreEqual("30", joined);
}
根据秒表,结果如下:TestMethod1 = 19msTestMethod2 = 7ms
感谢大家的回复
我同意大多数评论,我认为不进行单元测试可能会有所帮助。如果您使用LINQ,请使用LINQPad(免费标准版)来运行像这样的测试或其他小代码块。下面是测试,扩展到包括Regex,并增加到100000个循环。
void Main()
{
string text = "I want to find the number (30)";
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod1();
}
sw.Elapsed.TotalMilliseconds.Dump("Substring no parameter");
sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod1(text);
}
sw.Elapsed.TotalMilliseconds.Dump("Substring parameter");
sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod2();
}
sw.Elapsed.TotalMilliseconds.Dump("LINQ no parameter");
sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod2(text);
}
sw.Elapsed.TotalMilliseconds.Dump("LINQ parameter");
sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod3(text);
}
sw.Elapsed.TotalMilliseconds.Dump("Regex In");
sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
TestMethod4(text);
}
sw.Elapsed.TotalMilliseconds.Dump("Regex Out");
sw = Stopwatch.StartNew();
sw.Stop();
}
// Define other methods and classes here
public void TestMethod1()
{
string text = "I want to find the number (30)";
var startNumber = text.IndexOf('(');
var trimmed = text.Trim(')');
var number = trimmed.Substring(startNumber).Trim('(');
}
public void TestMethod1(string text)
{
var startNumber = text.IndexOf('(');
var trimmed = text.Trim(')');
var number = trimmed.Substring(startNumber).Trim('(');
}
public void TestMethod2()
{
string text = "I want to find the number (30)";
var lambdaNumber = text.Where(x => Char.IsNumber(x)).ToArray();
var joined = string.Join("", lambdaNumber);
}
public void TestMethod2(string text)
{
var lambdaNumber = text.Where(x => Char.IsNumber(x)).ToArray();
var joined = string.Join("", lambdaNumber);
}
public void TestMethod3(string text)
{
var regex = new Regex(@"('d+)");
var match = regex.Match(text);
var joined = match.Captures[0].Value;
}
public Regex regex = new Regex(@"('d+)");
public void TestMethod4(string text)
{
var match = regex.Match(text);
var joined = match.Captures[0].Value;
}
和结果:
Substring no parameter
11.3526
Substring parameter
10.2901
LINQ no parameter
60.2359
LINQ parameter
56.5218
Regex In
301.1179
Regex Out
89.8345
结论?我们还在拿苹果、橘子和钻石作比较。而且regex似乎没有一些人建议的那么快。专业工具才是正确的选择。