是什么导致字符串连接时间的这个峰值?

时间:2013-11-04 15:07:19

标签: c# performance string-concatenation stopwatch

因此,出于好奇心和无聊的无聊,我在基准Shlemiel the painter's algorithm时愚弄。我从一个空白字符串开始,创建了1000个空格中的另一个,然后使用普通的低效字符串连接开始向另一个添加一个,计算每次花费多长时间。

string s1 = "";
string s2 = "";
while (s2.Length < 1000)
{
    s2 += " ";
}

while (true)
{
    Stopwatch sw = Stopwatch.StartNew();
    s1 += s2;
    sw.Stop();

    Console.WriteLine(" {0}| {1}", s1.Length, sw.ElapsedMilliseconds);
}

正如预期的那样,字符串越长,连接所需的时间越长(它的影响比我预期的要小得多,但那是另一天的另一个问题)。然而, 令人惊讶的是它花费的时间一直是高峰。每六次连接大约需要前五次连接的两到三倍。

 Length     | Time (ms)
 -----------------------
 32250000   | 117
 32251000   | 44
 32252000   | 31
 32253000   | 30
 32254000   | 30
 32255000   | 32
 32256000   | 129
 32257000   | 35
 32258000   | 43
 32259000   | 34
 32260000   | 30
 32261000   | 29
 32262000   | 107
 32263000   | 47
 32264000   | 29
 32265000   | 30
 32266000   | 31
 32267000   | 29
 32268000   | 110
 32269000   | 46
 32270000   | 31
 32271000   | 30
 32272000   | 30
 32273000   | 30
 32274000   | 113

这些样本来自一旦字符串开始变得非常大,但模式从一开始就成立。很大程度上,前大约一千个样本太小而不能注意到图案,但是大约1.8k标记它是可识别的。

我的第一个假设是在幕后,角色被存储在某种ArrayList / vector类型的交易中,一旦它满了就会增加一倍,但是当我想到它时,它不适合 - 如果在这种情况下,峰值将呈指数周期而非线性。

所以,简而言之:这到底是怎么回事?

1 个答案:

答案 0 :(得分:3)

创建字符串并丢弃它们会产生垃圾。一旦您使用了一定量的内存,就会发生垃圾收集并暂停您的进程。由于你的过程中没有其他任何事情发生,并且你总是使你的字符串长度相同,所以GC总是在同一时间(每第6次运行)发生。

为了避免这种影响,请在每次运行时启动计时器之前调用GC.Collect