如何使用C#代码证明大对象一开始就会分配在2代堆中?

大对象指的是大于等于 85000 字节的对象。我这边使用 GC 类的静态方法进行获得,暂时还没有想到别的方法来获得,也没有想到能确切获得这个对象是不是大对象的方法

byte[] bigArray = new byte[85000];
Console.WriteLine(GC.GetGeneration(bigArray));

输出结果:

如何使用C#代码证明大对象一开始就会分配在2代堆中?


 可以看到,使用 GC.GetGeneration(Object) 只能看到这个对象处于 2 代中,但是如果要看是不是真的是大对象,可以使用一些性能调试软件看出。这里使用 CLRProfiler 进行查看,如下图:

如何使用C#代码证明大对象一开始就会分配在2代堆中?

我们分配的 Byte[] 是被分配在 LOH 中的。这说明,确实大小等于 85000 字节的对象直接被分配到了大对象堆中。


 最后,要注意的是,不能使用如下代码进行测试:

大对象声明:

public class BigObject
{
    public byte[] bigArray = new byte[85000];

    ~BigObject()
    {
        Console.WriteLine("BigObject Collected!");
    }
}

上端调用:

BigObject bigObj = new BigObject();
bigObj = null;

Console.WriteLine("0代、1代回收");
GC.Collect(1);

Console.ReadKey();

输出结果:

如何使用C#代码证明大对象一开始就会分配在2代堆中?

可以看到,这边这个 BigObject 被回收了,即使是将 GC.Collect 设置为 0 代也是一样回收。这个错误是一个误区,BigObject 的回收不会和它其中的 85000 字节的 bigArray 一起被回收,而是在 BigObject 被回收后 bigArray 还是存在于大对象堆中。其实 BigObject 开始的时候是如下图分配内存的

如何使用C#代码证明大对象一开始就会分配在2代堆中?

 

如何使用C#代码证明大对象一开始就会分配在2代堆中?

上一篇:1572: [Usaco2009 Open]工作安排Job


下一篇:AC自动机+全概率+记忆化DP UVA 11468 Substring