【发布时间】:2013-08-10 18:23:57
【问题描述】:
对下面的程序非常好奇(是的,在没有附加调试器的情况下以发布模式运行),第一个循环为数组的每个元素分配一个新对象,运行大约需要一秒钟。
所以我想知道哪个部分花费的时间最多——对象创建或分配。所以我创建了第二个循环来测试创建对象所需的时间,并创建了第三个循环来测试分配时间,两者都只运行了几毫秒。怎么回事?
static class Program
{
const int Count = 10000000;
static void Main()
{
var objects = new object[Count];
var sw = new Stopwatch();
sw.Restart();
for (var i = 0; i < Count; i++)
{
objects[i] = new object();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); // ~800 ms
sw.Restart();
object o = null;
for (var i = 0; i < Count; i++)
{
o = new object();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); // ~ 40 ms
sw.Restart();
for (var i = 0; i < Count; i++)
{
objects[i] = o;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); // ~ 50 ms
}
}
【问题讨论】:
-
在某些情况下,当循环对程序的其余部分没有明显影响时,抖动可以决定完全忽略循环。这可能是其中一种情况。您必须查看反汇编代码。
-
是的 jit 足够聪明,可以分析你的代码在第二个循环中什么都不做。
-
@SriramSakthivel 那么它不应该花费 40 毫秒。 JIT现在也很愚蠢。它不知道新对象什么都不做。
-
@mike z 垃圾收集不会立即发生。
-
这两种情况的不同之处在于,只有在情况 1 中,您才保留对不同对象的引用;在案例 2 中,您一次只引用一个对象,在案例 3 中,只有一个对象。我不认为这两个案例加起来与案例 1 相同。
标签: c# performance