Why memory alignment?

Let’s start with a question:

How much is this going to output? Is it a 1byte(1 byte) + int32(4) = 5 bytes? The answer is 8.

Access granularity: First, memory is in bytes. Of course, the processor will not read data byte by byte, which is inefficient. To improve the efficiency of reading, the processor can read a batch of bytes at a time. Such a batch can be 2, 4, 8, 16, and so on (2^n). This is called memory access granularity. Assuming that the access granularity is now 8, there is now one byte in the second location, and the CPU will read all eight, then remove the first and the next six, leaving the target byte.

What’s wrong with misalignment? Suppose the access granularity is now 8 and there are two pieces of data of 5 bytes each.

  • Not aligned

You can see that the second data is distributed between the first memory block (0-8) and the second memory block (8-16), so when the second data block is read, it is readtwo, then remove the first 5 bits of the first memory block, remove the last 6 bits of the second memory block, and then assemble.

  • alignment

The CPU can directly cut to the second memory block, read 8 bytes at a time, take the first 5 bytes, discard the last 3 bytes, and end, only need to read once.

Go Memory alignment

The alignment coefficient of go can be obtained from unbroadening.Alignof, and the occupancy length can be obtained from unbroadening.Sizeof.

  • unsafe.Alignof

Description of official documents:

  1. For a variable x of any type: unsafe.Alignof(x) is at least 1.
  2. For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe.Alignof(x.f) for each field f of x, but at least 1.
  3. For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array’s element type
  1. Any type alignment length must be at least 1
  2. For structs, align the length to the member with the maximum internal length
  3. For array types, the alignment length is the length of the element type (e.g. [2]int8 is int8 =1)
  • unsafe.Sizeof

Get type alignment length:

Alignment optimization:

  1. Based on rule 2 of unsafe.alignof, the alignment length of struct is 8
  2. A takes up one byte, the alignment length is 8, and the next element of A is C, so C takes up 8 bytes, so the first block wastes 7 bytes
  3. C takes up 8 bytes and fills up the second block
  4. B takes 4 bytes, and the third block wastes 4 bytes

The total usage is 24 bytes.

Let’s change the order of B and C:

  1. Based on rule 2 of unsafe.alignof, the alignment length of struct is 8
  2. A takes one byte, the alignment length is 8, and the next element of A is B, b takes four bytes, both a and B are in the first block, and the first block has three bytes left
  3. C is 8 bytes, and the remaining 3 bytes of the first block are not enough to fill the second block

The total usage is 16 bytes.

For struct types, proper order of members can reduce memory footprint.