Почему KeyValuePair‹int, long› 16 байт?

KeyValuePair<int, int>:    8 bytes
KeyValuePair<long, long>: 16 bytes
KeyValuePair<long, int>:  16 bytes (!!)
KeyValuePair<int, long>:  16 bytes (!!)

Я ожидаю, что последние две пары потребуют только 8 (long) + 4 (int) = 12 байтов. Почему они занимают 16?

Размеры определялись с помощью динамического SizeOf, переданного через ILGenerator, как описано здесь: Размер универсальной структуры


person Timo    schedule 02.02.2016    source источник
comment
en.wikipedia.org/wiki/Data_structure_alignment   -  person ChrisF    schedule 02.02.2016
comment
@PetSerAl Я получаю одинаковый результат для обоих, поэтому мне любопытны оба сценария.   -  person Timo    schedule 02.02.2016


Ответы (1)


Это связано с выравниванием структуры данных. Цитирую статью из Википедии:

Выравнивание данных означает размещение данных по адресу памяти, кратному размеру слова, что повышает производительность системы благодаря тому, как ЦП обрабатывает память. Чтобы выровнять данные, может потребоваться вставить несколько бессмысленных байтов между концом последней структуры данных и началом следующей, что является дополнением структуры данных.

Поскольку int составляет 4 байта, KeyValuePair имеет значение long, а int приведет к смещению структур данных. Это приведет к значительному падению производительности. Поэтому лучше «тратить» 4 байта на каждую запись, чтобы данные были выровнены и, следовательно, могли быть эффективно записаны и прочитаны.

Что касается того, почему одиночные целые числа не заполняются - не забывайте, что со структурой/классом относительно легко добавить переменную заполнения, но для простого типа значения у вас нет этой структуры/класса. Я предполагаю, что требуемая дополнительная работа (добавление фиктивной структуры вокруг int для вставки заполнения) не стоит увеличения производительности.

Здесь нет никакой разницы между 32-битными и 64-битными операционными системами, они все равно нуждаются в отступах и выравнивании, но количество отступов может различаться.

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

person ChrisF    schedule 02.02.2016
comment
Я ожидал чего-то в этом роде. Но я также отмечаю, что обычное целое не получает никакого заполнения, даже если оно не кратно 8 байтам. Допустимо ли его неправильное выравнивание? Это компромисс? У нас будет так много целых чисел, что мы захотим снизить производительность для экономии памяти, но KeyValuePair‹› будет достаточно редким, поэтому мы предпочли бы правильно его выровнять. Или я что-то упускаю? - person Timo; 02.02.2016
comment
Кроме того, имеет ли здесь значение 32-битная или 64-битная версия? Размеры предполагают, что нет. - person Timo; 02.02.2016
comment
@ Тимо нет, 32-битная или 64-битная не имеет значения. - person ChrisF; 02.02.2016