2012-03-28 16 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