2017-07-19 295 views
0

不是一个真正的问题,但我没有找到任何答案,所以我自己运行了一些测试,并认为其他人可能会受益。C#String.PadRight性能与连接字符串+ pad字符的子字符串

首先的问题是:

当填充一个(很多)字符串到与预定义的字符的预定义长度,是它更快地使用String.PadRight()或与预先设定的字符串的子串以连接串填充字符?

+0

目前还不清楚你试图填充或连接。所以这个问题只能由你自己来回答。 –

+0

我很肯定你会大大降低正确和有意义的基准测试的难度。 - 你也可能想看看c#源代码! – TaW

+0

@TimSchmelter嗯,我原本在一篇文章中有两个问题和答案,直到我看到我可以直接分解它们。但是因为我在回答问题的同时发布了答案,所以我认为只要没有人发现问题就足​​够了,可以从答案中得到更多关于我的目标的更多信息;) –

回答

2

我在找不到答案之后自己跑了测试(这是首先发布帖子的原因)。

我的结果如下(类似在多次运行)

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 
+0

Side -note:我可以推荐使用[BenchmarkDotNet](http://benchmarkdotnet.org/)进行此类测试。易于使用,结果更准确。记住要运行测试编译为发布和没有附加调试器(例如,作为一个控制台应用程序,不盯着视觉工作室)。当然,测试本身应该只测试他们应该做的事情,而不是不相关的代码(对于这两种方法来说都是平等的)。 –