内存对齐的现象:
之前没接触过c艹的同学可以先看下面的例子:
type A struct {
a bool
b string
c bool
}
type B struct {
a bool
c bool
b string
}
func main() {
fmt.Printf("Size A:%d\n", unsafe.Sizeof(A{}))
fmt.Printf("Size B:%d\n", unsafe.Sizeof(B{}))
}
输出结果是:
Size A:32
Size B:24
数据类型
我们接下来先简单讨论下go基本类型的空间分配
go底层对于数据类型的内存占用做了如下定义:基本类型和平台类型
基本类型是直接标识出类型占用字节数的:
var basicSizes = [...]byte{
Bool: 1,
Int8: 1,
Int16: 2,
Int32: 4,
Int64: 8,
Uint8: 1,
Uint16: 2,
Uint32: 4,
Uint64: 8,
Float32: 4,
Float64: 8,
Complex64: 8,
Complex128: 16,
}
平台类型则与运行环境相关(比如32位/64位等平台)
// StdSizes is a convenience type for creating commonly used Sizes.
// It makes the following simplifying assumptions:
//
// - The size of explicitly sized basic types (int16, etc.) is the
// specified size.
// - The size of strings and interfaces is 2*WordSize.
// - The size of slices is 3*WordSize.
// - The size of an array of n elements corresponds to the size of
// a struct of n consecutive fields of the array's element type.
// - The size of a struct is the offset of the last field plus that
// field's size. As with all element types, if the struct is used
// in an array its size must first be aligned to a multiple of the
// struct's alignment.
// - All other types have size WordSize.
// - Arrays and structs are aligned per spec definition; all other
// types are naturally aligned with a maximum alignment MaxAlign.
//
// *StdSizes implements Sizes.
//
type StdSizes struct {
WordSize int64 // word size in bytes - must be >= 4 (32bits)
MaxAlign int64 // maximum alignment in bytes - must be >= 1
}
注释写的很清楚:
// ...strings and interfaces is 2*WordSize.
// - The size of slices is 3*WordSize
// int占据的1个WordSize根据平台会分区分4||8字节
结构体内存对齐
这里来引入一个概念:内存对齐指内存中数据的首地址是CPU单次获取数据大小的整数倍,目的是为了减少cpu读取内存次数,加速操作
结构体对齐规则:
1 结构体成员最大的类型字节数为m,则结构体整体对齐后的字节数应该为m的倍数,不够的在最后面填补占位。
2 结构体某个成员的占用字节数为n, 则它的偏移地址应该是min(n,m)的整数倍。
由上面的类型占用定义可知:
bool 的对齐空间的1字节
int64的对齐空间的8字节
string 的对齐空间的8*2字节
所以,我们文章开头的那个demo的占用空间即可计算:
type A struct {
a bool
b string
c bool
}
/**
A内存占用:32字节
bool 1byte 补7byte
string 8*2byte(指针8byte, len 8byte,两个int)
bool 1byte 补7byte
**/
type B struct {
a bool
c bool
b string
}
/**
B内存占用:24字节
bool 1byte
bool 1byte
补8-1-1=6byte
string 8*2byte(指针8byte, len 8byte,两个int)
**/