2012-04-08 23 views
0

我有這個簡單的代碼:CLR GC的世代預算?

sealed class GenObj 
{ 
    ~GenObj() 
    { 
     Console.WriteLine("In Finalize method"); 
    } 
} 

public static class Program 
{ 
    public static void Main() 
    { 
     Console.WriteLine("Maximum generations: " + GC.MaxGeneration); 
     Object o = new GenObj(); 
     Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 3 
     GC.Collect(); 
     Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 5 
     GC.Collect(); 
     Console.WriteLine("Gen " + GC.GetGeneration(o)); // line 7 
     GC.Collect(); 
     Console.WriteLine("Gen " + GC.GetGeneration(o)); 

    } 
} 

輸出:

Maximum generations: 2 
Gen 0 
Gen 1 
Gen 2 
Gen 2 

但是有一個問題。

書(CLR通過C#)也說開頭:

當CLR初始化時,它爲所有三個 代選擇的預算。正如我前面提到的,第0代的預算是 約256 KB,第1代的預算約爲2 MB。

...

也許已經有幾個集合,但在 1代的對象僅進行檢查時,第1代達到其預算, 這通常需要一代0

的幾個垃圾收集問題:

在#4線我可以理解爲什麼它不在第1代(GC後從0移到1)

我不明白的是第7行。

根據這本書:the objects in generation 1 are examined only when generation 1 reaches its budget

我不認爲它已經達到了它的預算。所以我想它應該留在第一代!

根據這本書 - 它不應該轉移到第二代。

我在想什麼?

p.s.這裏是link其中有確切的文字(相信我我有PDF)從書

+5

我無法訪問本書,但可能是在討論用於決定是進行部分集合還是完整集合的啓發式方法 - 並且每次都強制執行完整集合。 – 2012-04-08 07:31:31

+0

@Damien_The_Unbeliever在我的回答中已經完成了 – 2012-04-08 17:46:49

回答

1

我相信達米恩是正確的。這本書描述了當你不強制進行垃圾收集時會發生什麼。但是你這樣做。因此,正確的文本可能會顯示如下內容:

可能有多個集合,但第1代中的對象僅在發生第1代GC時發生。第1代GC發生在第1代達到其預算時,通常需要幾代第0代垃圾收集,但您也可以通過致電GC.Collect(1)強制執行。

+0

已經在我的答案 – 2012-04-08 17:46:35

2

寫一封電子郵件給書的作者後,

,這是他的回答

的預算用來告訴GC這一代IT應該 收集。如果您打電話給GC.Collect自己,那麼您告訴GC 忽略預算並僅執行收集。您正在儘早推動 集合,以促進對老一代的對象。

1

不要相信你在書中讀到的所有東西。

當作者寫這本書時,他/她可能不完全理解這個話題。 作者寫了這本書後,實現可能已經改變。

這是我的理解:

初始GC預算由GC模式和機器配置決定。

小對象分配在gen0區域,移動到gen1區域,然後通常移動到gen2區域。 大對象被分配在大對象堆中,這被認爲是gen2。

+0

我知道里克特,但合謀是一樣的。我在CLR perf團隊工作了3年,並且已經閱讀/步入了許多CLR/mscorlib代碼,所以我知道我在說什麼。 – 2014-09-15 14:57:56

0

下面是測試GC預算的方式:

const int AllocSize = 64;   // 64 kb block 
    const int MaxBudget = 5 * 1024;  // Test max to 5 mb 

    static int GetG0Budget() 
    { 
     GC.Collect(0, GCCollectionMode.Forced, true); 

     int gcCount = GC.CollectionCount(0); 

     int sum = 0; 

     for (int i = 0; i < MaxBudget; i += AllocSize) 
     { 
      byte[] buffer = new byte[AllocSize * 1024]; 

      sum += buffer[0]; 

      if (GC.CollectionCount(0) != gcCount) 
      { 
       return i; 
      } 
     } 

     return MaxBudget + sum; 
    } 

嘗試在不同的機器,不同的值將被退回。例如,在強大的臺式機,筆記本電腦和Windows手機上試用它。