运行一个具有大量迭代的空 for 循环,运行所需的时间我得到了截然不同的数字:
public static class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 1000000000; ++i)
{
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
以上将在我的机器上运行大约 200 毫秒,但如果我将其增加到 1000000001,则需要4 倍的时间!然后如果我把它设为 1000000002,那么它又会下降到 200 毫秒!
这似乎发生在偶数次迭代中。如果我去for (var i = 1; i < 1000000001
,(注意从 1 而不是 0 开始)然后是 200 毫秒。或者如果我这样做i <= 1000000001
(注意小于或等于),那么它是 200 毫秒。或者(var i = 0; i < 2000000000; i += 2)
也一样。
这似乎只在 x64 上,但在所有 .NET 版本上(至少)4.0。此外,它仅在调试器分离的发布模式下出现。
更新我认为这可能是由于 jit 中的一些巧妙的位移,但以下似乎反驳了这一点:如果您在该循环中执行诸如创建对象之类的操作,那么这也需要大约 4 倍的时间:
public static class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
object o = null;
for (var i = 0; i < 1000000000; i++)
{
o = new object();
}
sw.Stop();
Console.WriteLine(o); // use o so the compiler won't optimize it out
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
这在我的机器上大约需要 1 秒,但随后增加 1 到 1000000001 需要4 秒。那是额外的 3000 毫秒,所以它不可能真的是由于位移,因为这也会显示为原始问题的 3000 毫秒差异。