结构体创建优化

题目来源: 映客

答案1:

这道题考察对结构体占用的空间的理解, 需要了解几个概念

go 结构体内存占用

go中一个结构体实例所占据的空间等于各字段占据空间之和,再加上内存对齐的空间大小。
tips: 可使用unsafe.Sizeof 查看struct占用的内存空间大小
unsafe.Alignof 方法,可以返回一个类型的对齐值,也可以叫做对齐系数或者对齐倍数。

内存对齐 memory alignment

CPU 访问内存时,并不是逐个字节访问,而是以字长(word size)为单位访问。比如 32 位的 CPU ,字长为 4 字节,那么 CPU 访问内存的单位也是 4 字节。
这么设计的目的,是减少 CPU 访问内存的次数,加大 CPU 访问内存的吞吐量。比如同样读取 8 个字节的数据,一次读取 4 个字节那么只需要读取 2 次。
CPU 始终以字长访问内存,如果不进行内存对齐,很可能增加 CPU 访问内存的次数

对齐保证 align guarantee

  1. 对于任意类型的变量 x ,unsafe.Alignof(x) 至少为 1。
  2. 对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。
  3. 对于 array 数组类型的变量 x,unsafe.Alignof(x) 等于构成数组的元素类型的对齐倍数。
  4. 没有任何字段的空 struct{} 和没有任何元素的 array 占据的内存空间大小为 0,不同的大小为 0 的变量可能指向同一块地址。

struct 内存对齐的技巧

字段顺序影响struct大小,因为每个字段按照自身的对齐倍数来确定在内存中的偏移量,字段排列顺序不同,上一个字段因偏移而浪费的大小也不同。

type demo1 struct { a int8 b int16 c int32 } type demo2 struct { a int8 c int32 b int16 } func main() { fmt.Println(unsafe.Sizeof(demo1{})) // 8 fmt.Println(unsafe.Sizeof(demo2{})) // 12 }

对内存特别敏感的结构体的设计上,我们可以通过调整字段的顺序,减少内存的占用。从小到大~

参考资料

https://geektutu.com/post/hpg-struct-alignment.html 非常详细,强推