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