因此,出于好奇心和无聊的无聊,我在基准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类型的交易中,一旦它满了就会增加一倍,但是当我想到它时,它不适合 - 如果在这种情况下,峰值将呈指数周期而非线性。
所以,简而言之:这到底是怎么回事?
答案 0 :(得分:3)
创建字符串并丢弃它们会产生垃圾。一旦您使用了一定量的内存,就会发生垃圾收集并暂停您的进程。由于你的过程中没有其他任何事情发生,并且你总是使你的字符串长度相同,所以GC总是在同一时间(每第6次运行)发生。
为了避免这种影响,请在每次运行时启动计时器之前调用GC.Collect。