紧密循环中对象初始化的执行时间

时间:2012-02-21 12:24:37

标签: c# .net for-loop benchmarking

我在c#中有三个运行相同代码但有一点差别的方法,我的第一个代码块是

Stopwatch s = new Stopwatch();
object o = new object();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    o.ToString();
    o.GetType();
    o.GetHashCode();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds); //3100ms

这需要3100毫秒才能运行。然后,如果我将对象初始化内容的内容增加到7200ms,我的代码块就像这样;

Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    object o = new object();
    o.ToString();
    o.GetType();
    o.GetHashCode();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);//7200ms

但是,如果我初始化我的对象但不使用任何方法,这个成本为652ms。我的代码就像这个,

Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 100000000; i++)
{
    object o = new object();
}
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);//625ms

所以我想知道,3100ms + 625ms与7200ms无法比较。是什么导致前两者之间的差异很大?

2 个答案:

答案 0 :(得分:3)

在你的第二个区块中,你在许多新对象上调用GetHashCode()。根据我的记忆,第一次在对象上调用未重写的GetHashCode()方法时,会为该对象分配一个同步块。这是相对昂贵的,虽然后续调用GetHashCode同一个对象(根据你的第一个代码)是便宜的。

因此有三点需要注意:

  • 对象分配成本(以及任何GC)
  • 首次调用方法的费用
  • 后续调用方法的费用

这当然是一种概括 - 许多方法花费相同的时间,无论你多少次调用它们,而其他方法可能比前10次调用慢,之后很快。我认为,在GetHashCode()的情况下,它的“首次通话是昂贵的”领域。尝试使用以某种简单方式覆盖GetHashCode()的类型,我怀疑你会发现时间一落千丈。

此外,GetType()可能需要一段时间才能在第一次调用时为Type构建object - 我不确定。基本上你在这里一起测量一堆不同的东西,这总是导致难以分析。

答案 1 :(得分:0)

我会用Refactor或类似的东西反编译方法,看看生成的IL。可能答案就在那里。

相关问题