因此,出于好奇和无聊,我在对画家的算法 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);
}
正如预期的那样,字符串越长,连接所需的时间就越长(它的影响比我预期的要小得多,但这是另一天的另一个问题)。然而,令人惊讶的是,它所花费的时间持续飙升。每六个连接所用的时间大约是前五个连接的两到三倍。
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 类型的交易中,一旦填满,它的大小就会翻倍,但当我想得更多时,这不合适——如果那是在这种情况下,尖峰将出现在指数周期中,而不是线性的。
所以,简而言之:这到底是怎么回事?