Будет ли мой объект помещен в кучу больших объектов?

#c# #memory-management #large-object-heap

#c# #управление памятью #куча больших объектов

Вопрос:

Когда среда 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 ?

Ответ №1:

Каждый из выделяемых вами массивов байтов обрабатывается отдельно от включающего класса. Таким образом, OneBigObject на самом деле является двумя разными объектами CLR. Один из них — экземпляр OneBigObject, который очень маленький и содержит только поле ссылки. Другой — фактический массив байтов из 100 000 экземпляров. Тот же принцип применим и к другим классам.

Классы и структуры не разделяются. В этом нет необходимости, потому что трудно представить, что кто-то создает тип, в котором достаточно фактических полей, чтобы сделать его размером 85 кб. Большие объекты, подобные вашему примеру, на самом деле состоят из ссылок и массивов ссылок и поэтому совсем не очень большие.

Ответ №2:

Размер TwoSmallObjects (без учета накладных расходов, которые имеет каждый объект) составляет всего 8 байт (16 в 64-разрядном процессе). Аналогично, размер MixedSizeObjects составляет всего 24 байта (48 на 64-разрядной версии).

Итак, чтобы ответить на ваш вопрос, ни один из этих объектов не попадает в LOH. Массивы, на которые они ссылаются, могут зависеть от размера каждого отдельного массива.

Я не могу себе представить, как будет работать система, которая будет работать так, как вы ожидаете. Особенно учитывая, что конструктор запускается после выделения объекта. Как распределитель узнает, что вы собираетесь назначить его полям, прежде чем вы действительно это сделаете? Должен ли он переместить объект в LOH, если вы это сделаете? Зачем ему выполнять всю эту работу, если это ничему не помогает.

Еще одна вещь, которая может помочь: если у вас есть тип ссылочного типа (а массив равен одному), поле не содержит объект. Он содержит только ссылку.

Комментарии:

1. Возможно, пример был плохим, но я не думаю, что это отвечает на вопрос о том, будут ли большие объекты разделены на составные части.

2. @Yuck У вас крайне маловероятно, что у вас есть класс, который не является массивом, который напрямую содержит элементы, занимающие более 85 000 байт. Может быть, если бы у вас был фиксированный элемент или что-то с FieldOffsets .

3. Почему нет? Дело в том, что если какой-либо объект имеет ссылку на большой объект, это не делает этот объект большим.