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

Mik*_*iar 5 c# performance stopwatch string-concatenation

因此,出于好奇心和无聊的无聊,我一直在为Shlemiel的画家算法进行基准测试.我从一个空白字符串开始,创建了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);
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,字符串越长,连接所用的时间就越长(它的影响比我预期的要小得多,但那是另一天的另一个问题).什么令人惊讶的,但是,在它花时间一致尖峰.每六次连接大约需要前五次连接的两到三倍.

 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
Run Code Online (Sandbox Code Playgroud)

这些样本从一旦字符串开始变得非常大,但从一开始就保持模式.很大程度上,前大约一千个样本太小而无法注意到图案,但在1.8k左右的标记处可以识别.

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

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

Gab*_*abe 4

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

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