Memory optimisation by re structuring GO struct

Identifying the problem(may be this is not right to call it problem, this is standard behaviour of how cpu accesses memory):

The CPU accesses memory by a single memory word at a time. As long as the memory word size is at least as large as the largest primitive data type supported by the computer, aligned accesses will always access a single memory word.

When the highest and lowest bytes of the datum are not in the same memory word the processor needs to access the data by doing multiple operations. This requires the processor to do many complex operations to generate memory accesses and coordinate them.

What is padding:

Though the compiler or may be interpreter normally allocates individual data items on aligned boundaries, data structures often have members with different alignment requirements. To maintain proper alignment the translator normally inserts additional unnamed data members so that each member is properly aligned. In addition, the data structure as a whole may be padded with a final unnamed member. This allows each member of an #struct to be properly aligned.

Now we know padding now let's learn when padding is used:

Padding is only inserted when a structure member is followed by a member with a larger alignment requirement or at the end of the structure. By changing the ordering of members in a structure, it is possible to change the amount of padding required to maintain alignment. For example, if members are sorted by descending alignment requirements a minimal amount of padding is required. The minimal amount of padding required is always less than the largest alignment in the structure.

Going over your head?

Here are some examples that will make things easy:

Let's consider an example:


type A struct {
  aBool? bool? ? // 1 byte
  aFloat float64 // 8 bytes
  aInt? ?int32? ?// 4 bytes
}        

So if we create a instance of this struct:

a := a{}        

what do you think the memory size will be taken by a? 13?

Unfortunately, No.

The total size will be 24 bytes.

why?

To keep field's data in a #word every member of the structure is padded to fill up the 8 bytes of a word. For the first element aBool the actual data takes 1 byte and the other 7 bytes are padded.

so the memory taken is now 8. Then consider aFloat as it takes 8 bytes no bytes need to be padded. so now the memory taken is 8+8 = 16 bytes. Now consider aInt, the actual data takes 4 bytes but another 4 bytes need to be padded. So the total memory consumed is now 8+8+8=24.

So how can we optimize this?

Let's look at the rearrangement.

type A struct {
  aFloat float64 // 8 bytes
  aBool? bool? ? // 1 byte
  aInt? ?int32? ?// 4 bytes
}        

It will now take just 16 bytes of memory. Phew! What an optimsation!

Let's explain:

aFloat is taking 8 bytes and filling the word and no padding is required. aBool is required 1 byte and another 7 bytes is going to be padded but as aInt require only 4 byte and it can be easily be in 7 bytes so no other extra allocation will be happened for aInt. So the total memory allocation will be now 8+8=16 bytes. Note: An alignment can be 1, 2, 4, or 8.

要查看或添加评论,请登录

Dipto Mondal的更多文章

  • Nodeport, TargetPort, Port

    Nodeport, TargetPort, Port

    Noobies like me get confused about what are nodeport , targetport and port and what are their usecases. Let's start by…

  • Let's Discuss STDIN, STDOUT and STDERR

    Let's Discuss STDIN, STDOUT and STDERR

    So what are stdin, stdout and stderr in linux or unix bash? Whenever we run a command in terminal the terminal creates…

    2 条评论

社区洞察

其他会员也浏览了