This is a creation in Article, where the information may have evolved or changed.
Recently doing some performance optimization work, one of the structure of the space occupied by the larger, and in the memory of the number is particularly large, just want to have no optimization of space, think of the C language inside the byte alignment, by simply adjusting the order of the field, you can save a lot of memory, this idea in Golang The same is true inside
Basic Data size
Before that, take a look at the size of the data in the basic type of Golang.
so (unsafe. Sizeof (True), shouldequal, 1) so (unsafe. Sizeof (int8 (0)), shouldequal, 1) so (unsafe. Sizeof (int16 (0)), shouldequal, 2) so (unsafe. Sizeof (Int32 (0)), shouldequal, 4) so (unsafe. Sizeof (Int64 (0)), shouldequal, 8) so (unsafe. Sizeof (int (0)), shouldequal, 8) so (unsafe. Sizeof (float32 (0)), shouldequal, 4) so (unsafe. Sizeof (float64 (0)), shouldequal, 8) so (unsafe. Sizeof (""), shouldequal, +) so (unsafe. Sizeof ("Hello World"), shouldequal, (+) so (unsafe. Sizeof ([]int{}), Shouldequal, () so (unsafe. Sizeof ([]int{1, 2, 3}, Shouldequal) so (unsafe. Sizeof ([3]int{1, 2, 3}, Shouldequal) so (unsafe. Sizeof (map[string]string{}), shouldequal, 8) so (unsafe. Sizeof (map[string]string{"1": "One", "2": "One"}), shouldequal, 8) so (unsafe. Sizeof (struct{}{}), shouldequal, 0)
- The bool type has only one bit, but it also takes 1 bytes because the computer is in bytes
- 64 for the machine, an int accounting for 8 bytes
- The string type is 16 bytes and contains a pointer to the data (8 bytes) and the length of an int (8 bytes).
- The slice type is 24 bytes and contains a pointer to the data (8 bytes) and the length of an int (8 bytes) and the capacity of an int (8 bytes).
- The map type takes 8 bytes and is a pointer to the map structure
- You can use struct{} to represent empty types, which do not occupy any space, use this as the value of map, you can say map as set to use
byte alignment
The fields in the structure are not compactly arranged in memory, but by byte-aligned, such as int accounted for 8 bytes, then can only write in the address of a multiple of the address, as to why the byte alignment, mainly for efficiency considerations, and the deeper principle looked at the online statement, feeling is not very reliable, It's not nonsense, I'm interested to study it myself.
// |x---|So(unsafe.Sizeof(struct { i8 int8}{}), ShouldEqual, 1)
Simply encapsulates a int8 structure, which, like int8, accounts for only 1 bytes, with no additional space
// |x---|xxxx|xx--|So(unsafe.Sizeof(struct { i8 int8 i32 int32 i16 int16}{}), ShouldEqual, 12)// |x-xx|xxxx|So(unsafe.Sizeof(struct { i8 int8 i16 int16 i32 int32}{}), ShouldEqual, 8)
The contents of the two structures are exactly the same, adjusting the order of the fields, saving 33% of space
// |x---|xxxx|xx--|----|xxxx|xxxx|So(unsafe.Sizeof(struct { i8 int8 i32 int32 i16 int16 i64 int64}{}), ShouldEqual, 24)// |x-xx|xxxx|xxxx|xxxx|So(unsafe.Sizeof(struct { i8 int8 i16 int16 i32 int32 i64 int64}{}), ShouldEqual, 16)
It is important to note that int64 can only appear at multiple addresses in multiples of 8, so there is a contiguous 4 bytes in the first struct that is empty
type I8 int8type I16 int16type I32 int32So(unsafe.Sizeof(struct { i8 I8 i16 I16 i32 I32}{}), ShouldEqual, 8)
The size of the type has not changed after renaming the type
Reprint please indicate the source
This article link: http://hatlonely.com/2018/03/
...