Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the concept of golang memory alignment

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "what is the concept of golang memory alignment". The editor shows you the operation process through an actual case. The operation method is simple and fast, and it is practical. I hope this article "what is the concept of golang memory alignment" can help you solve the problem.

What is memory alignment?

In order to ensure that the program runs smoothly and efficiently, the compiler will arrange various types of data to the appropriate address and occupy the appropriate length, which is memory alignment.

The alignment value of each type is its alignment boundary, and memory alignment requires that the data storage address and the number of bytes consumed should be a multiple of its alignment boundary. So the following int32 should be staggered by two bytes, starting at 4, but not immediately after 2.

It can also be explained like this:

CPU treats memory as a block, and the size of the block can be 2, 4, 8, and 16 bytes, so CPU reads memory one by one. The block size becomes memory access granularity (granularity).

If you don't do memory alignment

For example, we want to read 8 bytes of data starting with address 1:

CPU will be read twice:

The first time from 0-7, but only the last 7 bytes.

The second time from 8-15 but only the 1st byte.

Read it twice, which is bound to affect performance.

Why memory alignment?

There are two main reasons:

Platform reason (transplant reason): not all hardware platforms can access any data on any address; some hardware platforms can only take certain types of data at certain addresses, otherwise a hardware exception is thrown.

Performance reasons: data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that in order to access unaligned memory, the processor needs to make two memory accesses; aligned memory accesses require only one access.

Align the boundary

So how do you determine the alignment boundary for each type of data? This is related to platforms, which are supported by the go language:

You can see that on the common 32-bit platform, the pointer width and register width are 4 bytes, and on 64-bit platforms, it is 8 bytes. This value, which is called register width in go, can be understood as the machine word length and the maximum alignment boundary corresponding to the platform.

The alignment boundary of the data type is the smaller of the type size and the maximum alignment boundary of the platform. Note, however, that the same type may vary in size and alignment boundaries on different platforms.

Why not uniformly use the maximum alignment boundary of the platform? Or should it be aligned according to all types of sizes?

Let's give it a try, assuming that it is currently a 64-bit platform with a maximum alignment boundary of 8 bytes. Int8 is only 1 byte, and if it is aligned with 1 byte, it can be placed anywhere, because it can always be taken out in one read. If you uniformly align to 8 bytes, although you also only need to read once, each int8 variable will waste 7 bytes, so align to 1.

Int16 occupies 2 bytes, is aligned according to 2 bytes, can be saved from these addresses, and is guaranteed to be read only once.

If you press 1 byte alignment and it is possible to save it like this, you have to read it twice and then intercept the splicing, which will affect performance.

If you align to 8 bytes, it will waste memory as much as int8, so align to 2.

This is less than the maximum alignment boundary, and let's take a look at the case of greater than.

Suppose you want to store data of type int64 on a 32-bit platform, starting at location 8 when positions 0 and 1 are occupied. If you align to 4, you can start at location 4, with less memory waste, so choose to align to 4.

Therefore, the type alignment boundary will be selected in this way, still in order to reduce waste and improve performance.

GO calculates the alignment boundary function

In the go language, you can call unsafe.Alignof to return the corresponding type of alignment boundary:

Func main () {fmt.Printf ("bool align:% d\ n", unsafe.Alignof (bool (true) fmt.Printf ("int32 align:% d\ n", unsafe.Alignof (int32 (0) fmt.Printf ("int8 align:% d\ n", unsafe.Alignof (int8 (0)) fmt.Printf ("int64 align:% d\ n" Unsafe.Alignof (int64 (0)) fmt.Printf ("byte align:% d\ n", unsafe.Alignof (byte (0)) fmt.Printf ("string align:% d\ n", unsafe.Alignof ("EDDYCJY")) fmt.Printf ("map align:% d\ n", unsafe.Alignof (map [string] string {}))}

Running result:

Bool align: 1

Int32 align: 4

Int8 align: 1

Int64 align: 8

Byte align: 1

String align: 8

Map align: 8

Determine the alignment boundary of the structure

For a structure, we should first determine the alignment boundary of each member, and then take the largest one, which is the alignment boundary of the structure.

Then store this structure variable:

Memory alignment requirement 1:

Stores the starting address of this structure, which is a multiple of the alignment boundary.

Assuming that the memory starts at 0, each member of the structure will store the starting address as address 0, and then use the relative address to decide where to put it.

Memory alignment requirements 2:

The overall number of bytes occupied by the structure needs to be a multiple of the type alignment boundary, and if not enough, it needs to be expanded back.

So in the end, the size of the above structure type is 24 bytes.

Case

Type Part1 struct {a bool b int32 c int8 d int64 e byte} type Part2 struct {a bool c int8 e byte b int32 / / 4 bytes d int64}

Calculate the bytes occupied by the above two structures respectively:

Fmt.Printf ("part1 size:% d, align:% d\ n", unsafe.Sizeof (part1), unsafe.Alignof (part1)) fmt.Printf ("part2 size:% d, align:% d\ n", unsafe.Sizeof (part2), unsafe.Alignof (part2))

Here we call the function directly to get:

This is the end of part1 size: 32, align: 8part2 size: 16, align: 8 on "what is the concept of golang memory alignment". Thank you for reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report