当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
呢?
答案 0 :(得分:3)
您要分配的每个字节数组都与封闭类分开处理。所以OneBigObject实际上是两个不同的CLR对象。一个是非常小的OneBigObject实例,只包含一个引用字段。另一个是100,000个实例的实际字节数组。同样的原则也适用于其他类。
不拆分类和结构。没有必要,因为很难想象有人创建一个具有足够实际字段的类型,使其存储大小为85k。像你的例子一样,看起来很大的对象实际上由引用和引用数组组成,所以它们根本不是很大。
答案 1 :(得分:1)
TwoSmallObjects
的大小(忽略每个对象的开销)只有8个字节(64位进程中为16个字节)。同样,MixedSizeObjects
的大小只有24个字节(64位为48)。
所以,回答你的问题,这些对象都没有进入LOH。它们引用的数组可能会有所不同,具体取决于每个数组的大小。
我无法想象一个系统如何以你期望的方式工作。特别是考虑到构造函数在分配对象后运行。在实际执行此操作之前,分配器如何知道您要将哪些内容分配给其字段?如果你这样做,它应该将对象移动到LOH吗?如果它没有任何帮助,为什么它会完成所有工作。
另一件可能有用的事情:如果你有一种类型的引用类型(并且数组是一个),则该字段不包含该对象。它只包含引用。