原文:https://ms2008.github.io/2019/08/01/golang-memory-alignment/

内存模型

Posted by ms2008 on August 1, 2019

有些同学可能不知道,struct 中的字段顺序不同,内存占用也有可能会相差很大。比如:

type T1 struct {
a int8
b int64
c int16
} type T2 struct {
a int8
c int16
b int64
}

在 64 bit 平台上,T1 占用 24 bytes,T2 占用 16 bytes 大小;而在 32 bit 平台上,T1 占用 16 bytes,T2 占用 12 bytes 大小。可见不同的字段顺序,最终决定 struct 的内存大小,所以有时候合理的字段顺序可以减少内存的开销。

这是为什么呢?因为有内存对齐的存在,编译器使用了内存对齐,那么最后的大小结果就会不一样。至于为什么要做对齐,主要考虑下面两个原因:

  • 平台(移植性)

    不是所有的硬件平台都能够访问任意地址上的任意数据。例如:特定的硬件平台只允许在特定地址获取特定类型的数据,否则会导致异常情况

  • 性能

    若访问未对齐的内存,将会导致 CPU 进行两次内存访问,并且要花费额外的时钟周期来处理对齐及运算。而本身就对齐的内存仅需要一次访问就可以完成读取动作,这显然高效很多,是标准的空间换时间做法

有的小伙伴可能会认为内存读取,就是一个简单的字节数组摆放。但实际上 CPU 并不会以一个一个字节去读取和写入内存,相反 CPU 读取内存是一块一块读取的,块的大小可以为 2、4、6、8、16 字节等大小,块大小我们称其为内存访问粒度。假设访问粒度为 4,那么 CPU 就会以每 4 个字节大小的访问粒度去读取和写入内存。

在不同平台上的编译器都有自己默认的 “对齐系数”。一般来讲,我们常用的 x86 平台的系数为 4;x86_64 平台系数为 8。需要注意的是,除了这个默认的对齐系数外,还有不同数据类型的对齐系数。数据类型的对齐系数在不同平台上可能会不一致。例如,在 x86_64 平台上,int64 的对齐系数为 8,而在 x86 平台上其对齐系数就是 4。

还是拿上面的 T1、T2 来说,在 x86_64 平台上,T1 的内存布局为:

T2 的内存布局为(int16 的对齐系数为 2):

仔细看,T1 存在许多 padding,显然它占据了不少空间。那么也就不难理解,为什么调整结构体内成员变量的字段顺序就能达到缩小结构体占用大小的疑问了,是因为巧妙地减少了 padding 的存在。让它们更 “紧凑” 了。

其实内存对齐除了可以降低内存占用之外,还有一种情况是必须要手动对齐的:在 x86 平台上原子操作 64bit 指针。之所以要强制对齐,是因为在 32bit 平台下进行 64bit 原子操作要求必须 8 字节对齐,否则程序会 panic。详情可以参考 atomic 官方文档(这么重要的信息竟然放在页面的最底部!!!

Golang 是否有必要内存对齐?的更多相关文章

  1. golang内存对齐分析(转载)

    问题 type Part1 struct { a bool b int32 c int8 d int64 e byte } 在开始之前,希望你计算一下 Part1 共占用的大小是多少呢? func m ...

  2. Go中由WaitGroup引发对内存对齐思考

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 WaitGroup使用大家都会,但是其中是怎么实现的我们 ...

  3. 什么是内存对齐,go中内存对齐分析

    内存对齐 什么是内存对齐 为什么需要内存对齐 减少次数 保障原子性 对齐系数 对齐规则 总结 参考 内存对齐 什么是内存对齐 弄明白什么是内存对齐的时候,先来看一个demo type s struct ...

  4. C++内存对齐总结

    大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...

  5. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  6. C/C++ 知识点1:内存对齐

    预备知识:基本类型占用字节 在32位操作系统和64位操作系统上,基本数据类型分别占多少字节呢? 32位操作系统: char : 1    int :4    short : 2    unsigned ...

  7. Windows+GCC下内存对齐的常见问题

    结构/类对齐的声明方式 gcc和windows对于modifier/attribute的支持其实是差不多的.比如在gcc的例子中,内存对齐要写成: class X { //... } __attrib ...

  8. c++内存对齐

    内存对齐原则: 1.数据成员对齐规则:struct, union的数据成员,第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置.如在32bit的机 ...

  9. C语言中内存对齐

    今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...

随机推荐

  1. c++ c的拓展

    C++对c的拓展之, 引用和const关键字 bool类型关键字 C++中的布尔类型 C++在C语言的基本类型系统之上增加了bool C++中的bool可取的值只有true和false 理论上bool ...

  2. Java八大排序之堆排序

    堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法.堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点. 根据根结点是否是最 ...

  3. 调试CEF3程序的方法

    CEF3多进程模式调试时按F5只会启动调试Browser进程,要调试Renderer进程就要让进程在启动时就暂停并附加进程. 所幸google早就想到了这一点,chrome的命令行参数就可以办到, - ...

  4. JAVA类与类之间的关系及代码示例

    参考链接:https://blog.csdn.net/wq6ylg08/article/details/81092056

  5. destoon搜索伪静态失败解决办法

    今天给一个朋友调试DT6.0内核的站点,搜索中文出现http 403 forbidden,找了半天,很纳闷,最后一个一个查看源代码总算找到,在此分享给大家! 解决的方法: 1.找到include/sa ...

  6. android 判断是否真正连接到internet(通过检测网址,需要时间)

    if (InetAddress.getByName("www.xy.com").isReachable(timeout)) { } else { }

  7. Python实现电子词典(图形界面)

    Python实现电子词典(图形界面) 终端电子词典:https://www.cnblogs.com/noonjuan/p/11341375.html 文件一览: .├── client.py├── d ...

  8. django -- ORM实现作者增删改查

    前戏 前面我们已经实现了出版社的增删改查,书的增删改查,书和出版社的对应关系.现在来写一下作者的增删改查和书的对应关系,那书和作者有什么关系呢?一个作者可以写多本书,一本书可以有多个作者,所以书和作者 ...

  9. 洛谷 P1801 黑匣子_NOI导刊2010提高(06) 题解

    昨晚恶补了一下二叉堆的内容 然后就找了几个二叉堆的题来做awa 然后发现用二叉堆做这题复杂度是O(nlogn) 但是有O(n)的解法 (某大佬这么说) 思路大概就是: 利用一个大根堆一个小根堆来维护第 ...

  10. MOT19数据集百度云盘

    图片按视频分的压缩包 [已失效] 链接: https://pan.baidu.com/s/1kNw6yhvqgitNK5N__WOpxw 提取码: yia4 链接: https://pan.baidu ...