ric*_*cky 1 c# string concatenation
为什么速度排名是:AddStringInMutipleStatement> AddStringInOneStatement> AddStringInMutipleStatementEx?
它是否与运行时创建的临时字符串对象相关?细节是什么?
namespace Test
{
class Program
{
static string AddStringInOneStatement(int a, string b, int c, string d)
{
string str;
str = "a = " + a.ToString() + "b = " + b + "c = " + c.ToString() + "d = " + d;
return str;
}
static string AddStringInMutipleStatement(int a, string b, int c, string d)
{
string str = "";
str += "a = " + a.ToString();
str += "b = " + b;
str += "c = " + c.ToString();
str += "d = " + d;
return str;
}
static string AddStringInMutipleStatementEx(int a, string b, int c, string d)
{
string str = "";
str += "a = ";
str += a.ToString();
str += "b = ";
str += b;
str += "c = ";
str += c.ToString();
str += "d = ";
str += d;
return str;
}
static void Main(string[] args)
{
uint times = 10000000;
Stopwatch timer = new Stopwatch();
timer.Start();
for (int i = 0; i < times; i++)
{
AddStringInOneStatement(1, "2", 3, "4");
}
timer.Stop();
Console.WriteLine("First: " + timer.ElapsedMilliseconds); // 4341 ms
timer.Reset();
timer.Start();
for (int i = 0; i < times; i++)
{
AddStringInMutipleStatement(1, "2", 3, "4");
}
timer.Stop();
Console.WriteLine("Second: " + timer.ElapsedMilliseconds); // 3427 ms
timer.Reset();
timer.Start();
for (int i = 0; i < times; i++)
{
AddStringInMutipleStatementEx(1, "2", 3, "4");
}
timer.Stop();
Console.WriteLine("Second: " + timer.ElapsedMilliseconds); // 5701 ms
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,您的基准测试的几点:
GC.Collect()在每次测试后添加一个调用,这样一次测试创建的垃圾不会影响另一个测试这里有各种费用:
在第一种方法中,编译器实际上将您的代码转换为:
string[] bits = new string[] { "a = ", a.ToString(),
"b = ", b,
"c = ", c.ToString(),
"d = ", d };
return string.Concat(bits);
Run Code Online (Sandbox Code Playgroud)
第二种和第三种方法创建了几个中间字符串; 看起来它们创建了大致相同数量的中间体(因为第二种方法中的每一行创建了两个)但第三种方法需要更多复制 - 中间字符串都包含"到目前为止的整个字符串",而一半的中间字符串在第二种方法中只是短("b = " + b等).这可能是造成差异的原因.
我怀疑在这种情况下,第一种方法中数组创建(和填充)的成本超过了第二种方法中中间字符串的成本.实际上,将第一种方法更改为仅创建和填充数组,这似乎占用了超过运行时间的一半(在我的机器上).那个创造/人口也包括这些int.ToString()电话,请注意......这似乎也是费用的一大部分.
我已经删除了int.ToString()你的基准测试的本地副本中的部分,结果仍然存在 - 但更清晰,因为开销较少.