Почему структура .NET должна быть меньше 16 байт?

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

Но я не вижу, откуда это число (16).

Просматривая сеть, я нашел некоторых, которые предлагают приблизительное число для хорошей производительности, но Microsoft говорит, что это жесткий верхний предел. (например, MSDN)

Есть ли у кого-то окончательный ответ о том, почему это 16 байтов?

Ответ 1

Это просто правило производительности.

Дело в том, что поскольку типы значений передаются по значению, весь размер структуры должен быть скопирован, если он передан функции, тогда как для ссылочного типа необходимо скопировать только ссылку (4 байта), Структура может сэкономить немного времени, хотя, поскольку вы удаляете слой косвенности, поэтому, даже если он больше, чем эти 4 байта, он может быть более эффективным, чем передача ссылки. Но в какой-то момент он становится настолько большим, что стоимость копирования становится заметной. И общее правило состоит в том, что это обычно происходит около 16 байт. 16 выбрано потому, что это хорошее круглое число, сила двух, а альтернативы - либо 8 (что слишком мало, и сделает структуры почти бесполезными), либо 32 (в этот момент стоимость копирования структуры уже проблематична если вы используете структуры для повышения производительности)

Но в конечном итоге это рекомендация по производительности. Он отвечает на вопрос "что было бы наиболее эффективно использовать? Структура или класс?". Но он не отвечает на вопрос о том, "что лучше всего отображает в моей проблемной области".

Структуры и классы ведут себя по-разному. Если вам нужно поведение структуры, я бы сказал, чтобы сделать его структурой, независимо от размера. По крайней мере, пока вы не столкнетесь с проблемами производительности, прокомментируйте свой код и не обнаружите, что ваша структура является проблемой.

Ваша ссылка даже говорит, что это просто вопрос производительности:

Если одно или несколько из этих условий не выполняются, создайте ссылочный тип вместо структуры. Неспособность придерживаться этого руководства может негативно влияют на производительность.

Ответ 2

Если структура не превышает 16 байт, ее можно скопировать с помощью нескольких простых инструкций процессора. Если он больше, для копирования структуры используется цикл.

Пока структура не превышает 16 байт, процессор должен делать примерно такую ​​же работу при копировании структуры, как при копировании ссылки. Если структура больше, вы теряете преимущество производительности в структуре s, и обычно вы должны сделать ее классом.

Ответ 3

Размер размера в основном зависит от количества времени, необходимого для копирования структуры в стеке, например, для перехода к методу. Все, что намного больше, чем это, и вы потребляете много пространства стека, а циклы процессора просто копируют данные - когда ссылка на неизменяемый класс (даже с разыменованием) может быть намного более эффективной.

Ответ 4

Как отмечали другие ответы, стоимость байта за копирование структуры, которая превышает определенный порог (который был 16 байтов в более ранних версиях .NET, но с тех пор вырос до 20-24), значительно больше, чем стоимость каждого байта меньшей структуры. Важно отметить, однако, что копирование структуры any определенного размера once будет составлять часть стоимости, создавая новый экземпляр объекта класса того же размера. Если структура будет копироваться много раз за всю свою жизнь, а семантика значения типа не требуется, объект класса может быть предпочтительнее. Если, однако, структура будет скопирована только один или два раза, такое копирование, вероятно, будет дешевле, чем создание нового объекта класса. Постепенное количество копий, где объект класса будет дешевле, зависит от размера рассматриваемой структуры/объекта, но гораздо выше для вещей, которые ниже порога "дешевого копирования", чем для вещей выше.

Кстати, еще один момент, заслуживающий упоминания, заключается в том, что стоимость передачи структуры как параметра ref не зависит от размера структуры. Во многих случаях оптимальная производительность может быть достигнута путем использования типов значений и передачи их на ref. Однако следует быть осторожным, чтобы избежать использования свойств или полей readonly типов структуры, однако, поскольку доступ к любому из них создаст неявную временную копию рассматриваемой структуры.

Ответ 5

Вот сценарий, в котором структуры могут демонстрировать превосходную производительность:

Когда вам нужно создать 1000 экземпляров. В этом случае, если вы должны использовать класс, вам сначала нужно будет выделить массив для хранения 1000 экземпляров, а затем в цикле выделить каждый экземпляр. Но вместо этого, если вы будете использовать структуры, то 1000 экземпляров становятся доступными сразу же после выделения массива, который их удерживает.

Кроме того, структуры чрезвычайно полезны, когда вам нужно сделать interop или захотеть окунуться в небезопасный код по причинам производительности.

Как всегда есть компромисс, и нужно проанализировать, что они делают, чтобы определить лучший способ реализовать что-то.

ps: Этот сценарий вступил в игру, когда я работал с данными LIDAR, где могли быть миллионы точек, представляющих x, y, z и другие атрибуты для наземных данных. Эти данные необходимо было загрузить в память для некоторых интенсивных вычислений для вывода всех видов материалов.

Ответ 6

Я думаю, что 16 байт - это просто эмпирическое правило с точки зрения производительности. Объект в .NET использует по меньшей мере 24 байта памяти (IIRC), поэтому, если вы сделаете свою структуру намного больше, рекомендуется использовать ссылочный тип.

Я не могу придумать, почему они выбрали 16 байт.