我对垃圾收集过程有很多疑问,主要是它何时运行,何时将对象设置为老一代,等等......
static void Main(string[] args)
{
int i = 0, j = 0;
int a = 0;
Holder prev = new Holder(null);
while(GC.CollectionCount(1) == 0)
{
int aux = GC.CollectionCount(0);
if(aux > a){
a = aux;
++j;
Console.WriteLine((i+1));
}
++i;
Holder h = new Holder(prev);
Console.WriteLine(GC.GetGeneration(prev));
prev = h;
}
}
我正在尝试获取gen1中的对象数量。
为什么j = 1;
?? GC只在gen0上运行一次(暂时不应该至少运行2次)?
[编辑] 通过在休息之后添加这个,我非常困惑
Console.WriteLine("#gc0 = "+GC.CollectionCount(0)); --> 2
Console.WriteLine("#gc1 = "+GC.CollectionCount(1)); --> 1
Console.WriteLine("#objs = "+ i);
Console.ReadLine();
为什么GC.CollectionCount(0)只有2?我一直在通过c#阅读Richter clr,他说这个
检查第1代中的对象 只有当第1代达到预算时,通常需要几次垃圾收集 第0代。
[编辑]
但与此同时,如果gc看到所有对象都存活了,它会增加g0限制,也许是g0上只有2 gc的原因?
答案 0 :(得分:1)
我们如何用这样的随机性来调味:
class Program
{
static void Main(string[] args)
{
Random random = new Random();
int i = 0, j = 0;
int a = 0;
Holder prev = new Holder(null);
Holder prev2 = new Holder(null);
while (GC.CollectionCount(1) == 0)
{
int aux = GC.CollectionCount(0);
if (aux > a)
{
a = aux;
++j;
Console.WriteLine((i + 1));
}
++i;
var flag = random.Next(1) == 1;
Holder h = new Holder(flag ? prev : prev2);
Console.WriteLine("Prev: " + GC.GetGeneration(prev));
Console.WriteLine("Prev2: " + GC.GetGeneration(prev2));
if (flag)
{
prev = h;
}
else
{
prev2 = h;
}
}
}
}
internal class Holder
{
private Holder holder;
public Holder(Holder o)
{
holder = o;
}
}
您提供的代码示例非常简单,以至于CLR知道将prev
项移动到另一代并没有意义。
它的使用很简单,我认为运行时已将它优化为只能在G0上运行。
添加更复杂的逻辑会破坏运行时的优化,现在prev
或prev1
中的一个会进入G1,具体取决于较少使用的对象(不知道确切的机制)这里)。
您可以尝试添加代替prev
和prev2
prevs
数组,并在索引上随机执行,您可以更好地了解数组元素如何推进世代。