Royi Namir
Royi Namir

Reputation: 148534

CLR GC's Generations Budget?

I have this simple code :

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)); 

    }
}

output :

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

However there is a problem.

the book ( c# via clr) also says at the beginning :

When the CLR initializes, it selects budgets for all three generations. As I mentioned earlier, the budget for generation 0 is about 256 KB, and the budget for generation 1 is about 2 MB.

There might have been several collections, but the objects in generation 1 are examined only when generation 1 reaches its budget, which usually requires several garbage collections of generation 0.

question :

At line #4 I can understand why it is not in generation 1. ( moved from 0 to 1 after GC)

The line which I dont understand is line #7.

According to the book : the objects in generation 1 are examined only when generation 1 reaches its budget

I dont think it has already reached it budget. So i guess it should stay at Generation 1 !!!

ccording to the book - it shouldnt have moved to generation 2 .

What am i missing ?

p.s. here is the link which has the EXACT text ( believe me I have the PDF) from the book

Upvotes: 0

Views: 648

Answers (4)

Bye StackOverflow
Bye StackOverflow

Reputation: 245

Here is a way to test for GC budget:

    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;
    }

Try it on different machines, different values will be returned. For example, try it on powerful desktop, a laptop, a Windows phone.

Upvotes: 1

Bye StackOverflow
Bye StackOverflow

Reputation: 245

Do not believe everything you read in the book.

When the author wrote the book, he/she may not fully understand the topic. After the author wrote the book, implementation may have changed.

Here is my understanding:

initial GC budget is determined by gc mode and machine configuration.

Small objects are allocated in gen0 region, moved to gen1 region, then moved to gen2 region, normally. Large object are allocated in large object heap, which is considered gen2.

Upvotes: 1

Royi Namir
Royi Namir

Reputation: 148534

after writing an email to the author of the book ,

this was his answer

The budgets are used to tell the GC which generations IT should collect. If you call GC.Collect yourself, then you are telling the GC to ignore the budgets and to just do a collection. You are forcing the collection early which promotes objects to older generations.

Upvotes: 3

svick
svick

Reputation: 244848

I believe Damien is correct. The book describes what happens when you don't force full garbage collection. But you do that. So, the correct text could read something like this:

There might have been several collections, but the objects in generation 1 are examined only when generation 1 GC happens. And generation 1 GC happens when generation 1 reaches its budget, which usually requires several garbage collections of generation 0, but you can also force it by calling GC.Collect(1).

Upvotes: 1

Related Questions