golang的内存对齐

2021-04-20  本文已影响0人  Stevennnmmm

什么是内存对齐

type person struct {
    age int64
    height int64
}
func TestMdemo(t *testing.T) {
    fmt.Println(unsafe.Sizeof(person{}))
    fmt.Println(person{})
}

此时的 打印值为:16,一个64长度int占8字节,两个就是16。

type person struct {
    age int32
    height int64
}
func TestMdemo(t *testing.T) {
    fmt.Println(unsafe.Sizeof(person{}))
    fmt.Println(person{})
}

此时的 打印值为:16,4+8 =12 ,和我们预期不符合。这就是内存对齐现象。

为什么要对齐

那么关于golang如何对齐内存的呢。这里和cpu的访问数据是有关的。
cup访问内存并非按字节读取,而是按照 ”字长“ 来读取

计算机功能的强弱或性能的好坏,不是由某项指标决定的,而是由它的系统结构、指令系统、硬件组成、软件
配置等多方面的因素综合决定的。

计算机以及其相关的软件、硬件设备作为现代科学技术的结晶。应用于工业、商业、金融、教育、科研、军
事、通信及国防建设等国民经济的各个方面。诸多行业的发展对计算机科学愈来愈表现出强烈的依赖性。所以
计算机的评价与检测就十分重要。计算机功能的强弱或性能的好坏,不是由某项指标决定的,而是由它的系统
结构、指令系统、硬件组成、软件配置等多方面的因素综合决定的。

计算机在同一时间内处理的一组二进制数称为一个计算机的“字”,而这组二进制数的位数就是“字长”。在其他
指标相同时,字长越大计算机处理数据的速度就越快。早期的微型计算机的字长一般是8位和16位。586
(Pentium, Pentium Pro, PentiumⅡ,PentiumⅢ,Pentium 4)大多是32位,大多数人都装64位的了。

一般我们现在的服务器都是64位8字节的字长。那么实际上我们cpu读取一个8字节的数据只需要一次读取。

如何对齐 (对齐系数)

Size and alignment guarantees

type                                 size in bytes
byte, uint8, int8                     1
uint16, int16                         2
uint32, int32, float32                4
uint64, int64, float64, complex64     8
complex128                           16

保证”结构体“最小对齐

    For a variable x of any type: unsafe.Alignof(x) is at least 1.
    For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe
    .Alignof(x.f) for each field f of x, but at least 1.
    For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array's element type.

其实掌握了align 系数算法我们可以轻松算出struct 的size

利用对齐系数计算结构体大小

我们首先背下来官网的三个原则,就是上面写好了的。

我们来简单计算一下

type person struct {
    i int32
    i1 int32
}

size = size(i) +size(i1) : 8
align = align(i)/align(i1) :4  此时因为两个值的align相同
type person struct {
    i int32
    i1 int32
    i2 int64
}

size = 16      此时应该是size i +size i1 +size i2 = 4+4+8 =16
align = align(i2):8  此时因为两个值的align相同
type person struct {
    i int32
    i1 int64
}

size = 16      此时应该是size i +size i1  = 4+8 =12 ,但是应该size是 align 的倍数,所以最近就是16
align = align(i2):8  此时因为两个值的align相同

计算中的特殊情况

type person struct {
    i int32
    a struct{}
}
size = 8     
align = align(i2):4  此时取值align(4)

这里我们需要特殊说明一下情况:假设a 字段为空,那么如果这个结构体有个方法是返回a,具体如下

type person struct {
    i int32
    a struct{}
}
func (a *person)ted()interface{}{
    return a.a
}

这种情况就有可能出现内存泄露的情况。

上一篇 下一篇

猜你喜欢

热点阅读