Выравнивание памяти экземпляров классов - PullRequest
1 голос
/ 11 июля 2019

Я недавно прочитал интересную статью о производительности.

Там автор определил struct следующим образом:

public struct DecisionTreeNode
{
  public short ShortValue;
  public float FloatValue;
  public byte ByteVal1;
  public byte ByteVal2;
}

Значение этого struct составляет 8 байтов.

Все ясно, но затем он предложил, чтобы для достижения производительности, автор пишет:

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

Итак, он делает это:

public struct DecisionTreeNode
{
  public float FloatValue;
  public short ShortValue;
  public byte ByteVal1;
  public byte ByteVal2;
}

Как порядок полей в классе может повлиять на способ хранения экземпляра в памяти? Как это влияет на указанное выравнивание?

1 Ответ

1 голос
/ 11 июля 2019

у вас есть очень хорошее объяснение здесь:

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute.pack?view=netframework-4.7

https://kalapos.net/Blog/ShowPost/DotNetConceptOfTheWeek13_DotNetMemoryLayout

Все относится к полю Pack (размер его самого большого элемента или указанный атрибут размера упаковки => [StructLayout (LayoutKind.Sequential, Pack = X)], в зависимости от того, что меньше).

В соответствии с полем Pack структура будет последовательно группировать поля по размеру Pack и добавлять пустые байты для заполнения поля Pack.

struct => 1 байт + 8 байт + 1 байт => поле пакета => 8 => 8 + 8 + 8 = 24 байт

struct => 1 байт + 1 байт + 8 байт => поле пакета => 8 => 8 (1 + 1 + 6 пустых байтов) + 8 = 16 байтов.

Как вы всегда видите, группируйте поля, используя размер поля Pack.

...