问题
I know GC has 3 (0, 1, 2) generations but I'm wondering how GC decides the generation for a variable?
I thought all variables go into generation 0 and after some time move to generations 1 and 2. Is it size matter for GC to decide the generation?
Program1:
private static void Main(string[] args)
{
int a = 0;
string name = "Test";
var byteArray = new byte[10];
byteArray[4] = 4;
Console.WriteLine($"Generation of array {GC.GetGeneration(byteArray)}");
Console.WriteLine($"Generation of local int variable {GC.GetGeneration(a)}");
Console.WriteLine($"Generation of local string variable {GC.GetGeneration(name)}");
}
Result
Generation of array 0
Generation of local int variable 0
Generation of local string variable 0
Program2:
private static void Main(string[] args)
{
int a = 0;
string name = "Test";
var byteArray = new byte[100000000];
byteArray[4] = 4;
Console.WriteLine($"Generation of array {GC.GetGeneration(byteArray)}");
Console.WriteLine($"Generation of local int variable {GC.GetGeneration(a)}");
Console.WriteLine($"Generation of local string variable {GC.GetGeneration(name)}");
}
Result
Generation of array 2
Generation of local int variable 0
Generation of local string variable 0
回答1:
I'm wondering how GC decides the generation for a variable?
Variables are not GC'd in the first place. Objects of reference type are GC'd. Those objects contain variables, but it is the object that is collected.
I thought all variables go into generation 0 and after some time move to generations 1 and 2.
No. Don't think in terms of variables. Think in terms of objects. A newly-allocated object goes in gen0. If that object survives a collection, it is moved to gen1. If it survives another collection, it moves to gen2.
So now you know why calling GetGeneration
on a local variable containing an int will always return zero. It is not because the local is somehow magically associated with gen0. The local is not an object of reference type, and neither is its value!
When you pass the int to GetGeneration
the int is boxed into an object; that object is newly allocated and so it is in generation 0. This tells you nothing about the variable. If you pass any (non-null) value type to GetGeneration
that triggers an allocation, and obviously that allocation is gen0.
Again, your question indicates that you think that the GC is looking at the lifetimes of variables. It is not. It is looking at the lifetimes of objects of reference type.
Is it size matter for GC to decide the generation?
Yes. Extremely large arrays, for example, are allocated from a special "large object heap". By "extremely large", we mean basically any object on the order of 85KB or bigger. The large object heap is (1) not compacted, and (2) only collected when the regular heap does a gen2 collection.
回答2:
The generations 0 and 1 need to be small so they can be collected quickly. To keep them small, very large objects are allocated directly in generation 2.
来源:https://stackoverflow.com/questions/41521919/how-garbage-collection-decides-generation-for-variable