Golang内存对齐

如何得到一个对象所占内存大小?

fmt.Println(unsafe.Sizeof(int64(0))) // "8"

type SizeOfA struct {
    A int
}
unsafe.Sizeof(SizeOfA{0}) // 8

type SizeOfC struct {
    A byte  // 1字节
    C int32 // 4字节
}
unsafe.Sizeof(SizeOfC{0, 0})    // 8
unsafe.Alignof(SizeOfC{0, 0}) // 4
结构体中A byte占1字节,C int32占4字节. SizeOfC占8字节

内存对齐:

为何会有内存对齐?1.并不是所有硬件平台都能访问任意地址上的任意数据。2.性能原因 访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存只需访问一次。
上面代码SizeOfC中元素一共5个字节,而实际结构体占8字节
是因为这个结构体的对齐倍数Alignof(SizeOfC) = 4.也就是说,结构体占的实际大小必须是4的倍数,也就是8字节。

type SizeOfD struct {
    A byte
    B [5]int32
}
unsafe.Sizeof(SizeOfD{})   // 24
unsafe.Alignof(SizeOfD{})  // 4

Alignof返回的对齐数是结构体中最大元素所占的内存数,不超过8,如果元素是数组那么取数组类型所占的内存值而不是整个数组的值

type SizeOfE struct {
    A byte  // 1
    B int64 // 8
    C byte  // 1
}
unsafe.Sizeof(SizeOfE{})    // 24
unsafe.Alignof(SizeOfE{}) // 8

SizeOfE中,元素的大小分别为1,8,1,但是实际结构体占24字节,远超元素实际大小,因为内存对齐原因,最开始分配的8字节中包含了1字节的A,剩余的7字节不足以放下B,又为B分配了8字节,剩余的C独占再分配的8字节。

type SizeOfE struct {
    A byte  // 1
    C byte  // 1
    B int64 // 8    
}
unsafe.Sizeof(SizeOfE{})    // 16
unsafe.Alignof(SizeOfE{}) // 8

换一种写法,把A,C放到上面,B放到下面。这时SizeOfE占用的内存变为了16字节。因为首先分配的8字节足以放下A和C,省去了8字节的空间。
上面一个结构体中元素的不同顺序足以导致内存分配的巨大差异。前一种写法产生了很多的内存空洞,导致结构体不够紧凑,造成内存浪费。

下面我们来看一下结构体中元素的内存布局:

unsafe.Offsetof:返回结构体中元素所在内存的偏移量

type SizeOfF struct {
    A byte
    C int16
    B int64
    D int32
}
unsafe.Offsetof(SizeOfF{}.A) // 0
unsafe.Offsetof(SizeOfF{}.C) // 2
unsafe.Offsetof(SizeOfF{}.B) // 8
unsafe.Offsetof(SizeOfF{}.D) // 16

下图为内存分布图:


SizeOfF 内存布局图

蓝色区域是元素实际所占内存,灰色为内存空洞。

下面总结一下go语言中各种类型所占内存大小(x64环境下):

X64下1机器字节=8字节


Golang内置类型占用内存大小

总结一下:

从例子中可以看出,结构体中元素不同顺序的排列会导致内存分配的极大差异,不好的顺序会产生许多的内存空洞,造成大量内存浪费。
虽然这几个函数都在unsafe包中,但是他们并不是不安全的。在需要优化内存空间时这几个函数非常有用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • unsafe 包简单说明 unsafe,顾名思义,是不安全的,Go定义这个包名也是这个意思,让我们尽可能的不要使用...
    Gopherzhang阅读 5,420评论 8 3
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,794评论 1 32
  • 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站...
    小陈阿飞阅读 4,191评论 0 1
  • 感恩感谢被照顾。今天再次被我家荣荣的厨艺征服,自制全素麻辣香锅,太棒了!还有佳佳大盆友蒸的米饭。 感恩感谢旁观。今...
    enhui1994阅读 1,170评论 0 1
  • 近来总是做梦,一做一个晚上。醒来什么都忘了,有时能记住一点,有时一点也记不住了。 梦终究是梦,它是见不了阳光的。梦...
    滴水穿石910阅读 1,092评论 0 1