2012-03-28 17 views
9

GC.SuppressFinalize与可正常不可终结对象相同的可终止对象?下面的代码似乎证明他们区别对待,无论是在.NET 2和4:GC.SuppressFinalize与非可终结对象相比的性能

class Class1 { 

    public Class1() 
    { 
     GC.SuppressFinalize(this); 
    } 

    //~Class1() { } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     for (int i=0; i<100000000; i++) 
     { 
      new Class1(); 
     } 

     sw.Stop(); 
     Console.WriteLine(sw.ElapsedMilliseconds); 
    } 
} 

添加终结,而不是其他任何变动,会导致代码相比,采取远远较长(12601毫秒889毫秒)。

我认为SuppressFinalize在对象头文件中设置了一点,使得GC将对象看作是不可终止的对象,但这似乎并不是这种情况。发生什么了?一个不可终结的对象和GC.SuppressFinalize上调用的可终结对象之间有什么不同?

+2

也在.net 4.5 beta版本上声明了这一点 – 2012-03-28 17:58:21

+0

顺便提一下,我重复了这个测试,而是计算了执行GC.Collect()所需的时间。 GC.WaitForPendingFinalizers(); GC.Collect();'在所有'new's之后。没有(压制)终结者没有明显的区别。 – dlf 2017-07-27 20:59:44

回答

7

据我所知,CLR有一个已完成注册的对象队列。实现一个终结器将把类型的对象放在队列中。所以在构造函数调用SuppressFinalize的情况下,我认为该对象实际上被放在队列中,只能立即移除,这可以解释开销。

+3

你的想象力是准确的:) – 2012-03-28 23:29:21

+1

这似乎效率很低。不可终止的对象_应该与被压缩的可终止对象完全相同。令人惊讶的是它不同 – thecoop 2012-03-29 08:01:04

+0

@thecoop:或许,但是任何实现终结器的类型在构建时都需要区别对待。我想你可以做一个优化来检查在构造函数中是否抑制了finalization,但我不相信这是值得的。在通常情况下,抑制发生在对象构建后的一段时间。 – 2012-03-29 14:58:35