我的物体会被放置在大物体堆中吗?

时间:2011-10-25 01:18:56

标签: c# memory-management large-object-heap

当CLR在大对象堆上放置一个对象时,它是“全有或全无”交易吗?类/结构成员是否“分开”并放在不同的堆中?

class OneBigObject
{
    byte[] bigObject;

    public OneBigObject()
    {
        bigObject = new byte[100000];
    }
}

class TwoSmallObjects
{
    byte[] smallObject1;
    byte[] smallObject2;

    public TwoSmallObjects()
    {
        smallObject1 = new byte[50000];
        smallObject2 = new byte[50000];
    }
}

class MixedSizeObjects
{
    byte[] smallObject1;
    byte[] smallObject2;
    byte[] bigObject;

    public MixedSizeObjects()
    {
        smallObject1 = new byte[50000];
        smallObject2 = new byte[50000];
        bigObject = new byte[100000];
    }
}

OneBigObject oneBigObject = new OneBigObject();
TwoSmallObjects twoObjects = new TwoSmallObjects();
MixedSizeObjects mixedSizeObjects = new MixedSizeObjects();

TwoSmallObjects是否放在大对象堆上,因为它的总大小超过85,000字节?即使两个成员都处于门槛之下?那么MixedSizeObjects呢?

2 个答案:

答案 0 :(得分:3)

您要分配的每个字节数组都与封闭类分开处理。所以OneBigObject实际上是两个不同的CLR对象。一个是非常小的OneBigObject实例,只包含一个引用字段。另一个是100,000个实例的实际字节数组。同样的原则也适用于其他类。

不拆分类和结构。没有必要,因为很难想象有人创建一个具有足够实际字段的类型,使其存储大小为85k。像你的例子一样,看起来很大的对象实际上由引用和引用数组组成,所以它们根本不是很大。

答案 1 :(得分:1)

TwoSmallObjects的大小(忽略每个对象的开销)只有8个字节(64位进程中为16个字节)。同样,MixedSizeObjects的大小只有24个字节(64位为48)。

所以,回答你的问题,这些对象都没有进入LOH。它们引用的数组可能会有所不同,具体取决于每个数组的大小。

我无法想象一个系统如何以你期望的方式工作。特别是考虑到构造函数在分配对象后运行。在实际执行此操作之前,分配器如何知道您要将哪些内容分配给其字段?如果你这样做,它应该将对象移动到LOH吗?如果它没有任何帮助,为什么它会完成所有工作。

另一件可能有用的事情:如果你有一种类型的引用类型(并且数组是一个),则该字段不包含该对象。它只包含引用