不是一个真正的问题,但我没有找到任何答案,所以我自己运行了一些测试,并认为其他人可能会受益。C#String.PadRight性能与连接字符串+ pad字符的子字符串
首先的问题是:
当填充一个(很多)字符串到与预定义的字符的预定义长度,是它更快地使用String.PadRight()
或与预先设定的字符串的子串以连接串填充字符?
不是一个真正的问题,但我没有找到任何答案,所以我自己运行了一些测试,并认为其他人可能会受益。C#String.PadRight性能与连接字符串+ pad字符的子字符串
首先的问题是:
当填充一个(很多)字符串到与预定义的字符的预定义长度,是它更快地使用String.PadRight()
或与预先设定的字符串的子串以连接串填充字符?
我在找不到答案之后自己跑了测试(这是首先发布帖子的原因)。
我的结果如下(类似在多次运行)
direct String.PadRight average: 29,291921 ms.
String.PadRight average: 32,328434 ms.
Custom PadRight average: 27,066596 ms.
与
private const int Iterations = 500;
private const int NumStrings = 250000;
private const int TestStringLength = 50;
对于其中我生成的小于TestStringLength
字符NumStrings
随机串的测试,然后填充所有的他们到TestStringLength
与空白。
所以基于子字符串的填充似乎更快(但当然不太通用)。有趣的是,这种趋势反过来,填充的字符串越少,迭代次数越少。然后,String.PadRight
变得更快。
测试代码(here a dotnetfiddle version [减少计数,使其工作在那里,你不能相信你到达那里的结果,他们各不相同跑了很多运行):
#region Performance Test
private const int Iterations = 500;
private const int NumStrings = 250000;
private const int TestStringLength = 50;
private static string EmptyLine;
public static string PadRight(string input)
{
return input.PadRight(TestStringLength, ' ');
}
public static string PadRight2(string input)
{
return input + EmptyLine.Substring(0, TestStringLength - input.Length);
}
#endregion // Performance Test
与循环正在
#region Performance Test
EmptyLine = String.Join("", Enumerable.Repeat(" ", TestStringLength));
var random = new System.Random();
StringBuilder temp = new StringBuilder();
string[] randomStrings = new string[NumStrings];
double[] averageDirect = new double[Iterations];
double[] averageStandard = new double[Iterations];
double[] averageCustom = new double[Iterations];
// init random strings
for (int i = 0; i < NumStrings; ++i)
{
temp.Clear();
for (int k = 0; k < random.Next(0, TestStringLength); ++k)
{
temp.Append((char)('!' + random.Next(0, 93)));
}
randomStrings[i] = temp.ToString();
}
var timer = new Stopwatch();
string padded;
for (int counter = 0; counter < Iterations; ++counter)
{
timer.Reset();
timer.Start();
for (int i = 0; i < NumStrings; ++i)
{
padded = PadRight2(randomStrings[i]);
}
timer.Stop();
averageCustom[counter] = timer.Elapsed.TotalMilliseconds;
timer.Reset();
timer.Start();
for (int i = 0; i < NumStrings; ++i)
{
padded = PadRight(randomStrings[i]);
}
timer.Stop();
averageStandard[counter] = timer.Elapsed.TotalMilliseconds;
timer.Reset();
timer.Start();
for (int i = 0; i < NumStrings; ++i)
{
padded = randomStrings[i].PadRight(TestStringLength, ' ');
}
timer.Stop();
averageDirect[counter] = timer.Elapsed.TotalMilliseconds;
}
Console.WriteLine($"direct String.PadRight average: {averageDirect.Average()} ms.");
Console.WriteLine($"String.PadRight average: {averageStandard.Average()} ms.");
Console.WriteLine($"Custom PadRight average: {averageCustom.Average()} ms.");
#endregion // Performance Test
Side -note:我可以推荐使用[BenchmarkDotNet](http://benchmarkdotnet.org/)进行此类测试。易于使用,结果更准确。记住要运行测试编译为发布和没有附加调试器(例如,作为一个控制台应用程序,不盯着视觉工作室)。当然,测试本身应该只测试他们应该做的事情,而不是不相关的代码(对于这两种方法来说都是平等的)。 –
目前还不清楚你试图填充或连接。所以这个问题只能由你自己来回答。 –
我很肯定你会大大降低正确和有意义的基准测试的难度。 - 你也可能想看看c#源代码! – TaW
@TimSchmelter嗯,我原本在一篇文章中有两个问题和答案,直到我看到我可以直接分解它们。但是因为我在回答问题的同时发布了答案,所以我认为只要没有人发现问题就足够了,可以从答案中得到更多关于我的目标的更多信息;) –