以下 C# 代码需要 5 分钟才能运行:
int i = 1;
string fraction = "";
while (fraction.Length < 1000000)
{
fraction += i.ToString();
i++;
}
像这样“优化它”会导致它在 1.5 秒内运行:
int i = 1;
string fraction = "";
while (fraction.Length < 1000000)
{
// concatenating strings is much faster for small strings
string tmp = "";
for (int j = 0; j < 1000; j++)
{
tmp += i.ToString();
i++;
}
fraction += tmp;
}
编辑:有些人建议使用 StringBuilder
,这也是一个很好的建议,结果在 0.06 秒时出现:
int i = 1;
StringBuilder fraction = new StringBuilder();
while (fraction.Length < 1000000)
{
fraction.Append(i);
i++;
}
寻找 j
的最佳值是另一个话题,但为什么这种不明显的优化效果如此好?此外,在相关主题上,我听说您永远不应该对字符串使用 +
运算符,而应使用 string.Format()
,这是真的吗?
最佳答案
我根本没有得到你的结果。在我的盒子上,StringBuilder 轻松获胜。你能发布你的完整测试程序吗?这是我的,具有三个变体 - 您的字符串连接优化、“简单”的 StringBuilder 和具有初始容量的 StringBuilder。我增加了限制,因为它在我的盒子上运行得太快以至于无法有效测量。
using System;
using System.Diagnostics;
using System.Text;
public class Test
{
const int Limit = 4000000;
static void Main()
{
Time(Concatenation, "Concat");
Time(SimpleStringBuilder, "StringBuilder as in post");
Time(SimpleStringBuilderNoToString, "StringBuilder calling Append(i)");
Time(CapacityStringBuilder, "StringBuilder with appropriate capacity");
}
static void Time(Action action, string name)
{
Stopwatch sw = Stopwatch.StartNew();
action();
sw.Stop();
Console.WriteLine("{0}: {1}ms", name, sw.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
}
static void Concatenation()
{
int i = 1;
string fraction = "";
while (fraction.Length < Limit)
{
// concatenating strings is much faster for small strings
string tmp = "";
for (int j = 0; j < 1000; j++)
{
tmp += i.ToString();
i++;
}
fraction += tmp;
}
}
static void SimpleStringBuilder()
{
int i = 1;
StringBuilder fraction = new StringBuilder();
while (fraction.Length < Limit)
{
fraction.Append(i.ToString());
i++;
}
}
static void SimpleStringBuilderNoToString()
{
int i = 1;
StringBuilder fraction = new StringBuilder();
while (fraction.Length < Limit)
{
fraction.Append(i);
i++;
}
}
static void CapacityStringBuilder()
{
int i = 1;
StringBuilder fraction = new StringBuilder(Limit + 10);
while (fraction.Length < Limit)
{
fraction.Append(i);
i++;
}
}
}
结果:
Concat: 5879ms
StringBuilder as in post: 206ms
StringBuilder calling Append(i): 196ms
StringBuilder with appropriate capacity: 184ms
你的连接比第一个解决方案更快的原因很简单 - 你正在做几个“便宜”的连接(每次复制相对较少的数据)和相对较少的“大”连接(整个字符串至今)。原来,每一步都会复制目前得到的所有数据,显然代价更大。
关于c# - C#中的字符串操作优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/282468/