【golang】内存对齐

什么是内存对齐

在访问特定类型变量的时候通常在特定的内存地址访问,这就需要对这些数据在内存中存放的位置有限制,各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

内存对齐是编译器的管辖范围。表现为:编译器为程序中的每个“数据单元”安排在适当的位置上。

为什么需要内存对齐

  • 有些CPU可以访问任意地址上的任意数据,而有些CPU只能在特定地址访问数据,因此不同硬件平台具有差异性,这样的代码就不具有移植性,如果在编译时,将分配的内存进行对齐,这就具有平台可以移植性了。

  • CPU 访问内存时并不是逐个字节访问,而是以字长(word size)为单位访问,例如 32位的CPU 字长是4字节,64位的是8字节。如果变量的地址没有对齐,可能需要多次访问才能完整读取到变量内容,而对齐后可能就只需要一次内存访问,因此内存对齐可以减少CPU访问内存的次数,加大CPU访问内存的吞吐量。

假设每次访问的步长为4个字节,如果未经过内存对齐,获取b的数据需要进行两次内存访问,最后再进行数据整理得到b的完整数据:

在这里插入图片描述如果经过内存对齐,一次内存访问就能得到b的完整数据,减少了一次内存访问:

在这里插入图片描述

golang中unsafe.AlignOf()函数

unsafe.AlignOf(x) 方法的返回值是 m,当变量进行内存对齐时,需要保证分配到 x 的内存地址能够整除 m。因此可以通过这个方法,确定变量x 在内存对齐时的地址:

  • 对于任意类型的变量 x ,unsafe.Alignof(x) 至少为 1。
  • 对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。
  • 对于 array 数组类型的变量x,unsafe.Alignof(x) 等于构成数组的元素类型的对齐倍数。

对于系统内置基础类型变量 x ,unsafe.Alignof(x) 的返回值就是 min(字长/8,unsafe.Sizeof(x)),即计算机字长与类型占用内存的较小值:

func main() {fmt.Println(unsafe.Alignof(int(1))) // 1 -- min(8,1)fmt.Println(unsafe.Alignof(int32(1))) // 4 -- min (8,4)fmt.Println(unsafe.Alignof(int64(1))) // 8 -- min (8,8)fmt.Println(unsafe.Alignof(complex128(1))) // 8 -- min(8,16)
}  

内存对齐规则

  • 成员对齐规则

针对一个基础类型变量,如果 unsafe.AlignOf() 返回的值是 m,那么该变量的地址需要 被m整除 (如果当前地址不能整除,填充空白字节,直至可以整除)。

  • 整体对齐规则

针对一个结构体,如果 unsafe.AlignOf() 返回值是 m,需要保证该结构体整体内存占用是 m的整数倍,如果当前不是整数倍,需要在后面填充空白字节。

通过内存对齐后,就可以在保证在访问一个变量地址时:

  1. 如果该变量占用内存小于字长:保证一次访问就能得到数据;
  2. 如果该变量占用内存大于字长:保证第一次内存访问的首地址,是该变量的首地址。

eg:

type A struct {a int32b int64c int32
}func main() {fmt.Println(unsafe.Sizeof(A{1, 1, 1}))  // 24
}
  1. 第一个字段是 int32 类型,unsafe.Sizeof(int32(1))=4,内存占用为4个字节,同时unsafe.Alignof(int32(1)) = 4,内存对齐需保证变量首地址可以被4整除,我们假设地址从0开始,0可以被4整除:

在这里插入图片描述
2. 第二个字段是 int64 类型,unsafe.Sizeof(int64(1)) = 8,内存占用为 8 个字节,同unsafe.Alignof(int64(1)) = 8,需保证变量放置首地址可以被8整除,当前地址为4,距离4最近的且可以被8整除的地址为8,因此需要添加四个空白字节,从8开始放置:
S

  1. 第三个字段是 int32 类型,unsafe.Sizeof(int32(1))=4,内存占用为4个字节,同时unsafe.Alignof(int32(1)) = 4,内存对齐需保证变量首地址可以被4整除,当前地址为16,16可以被4整除:
    在这里插入图片描述

  2. 所有成员对齐都已经完成,现在我们需要看一下整体对齐规则:unsafe.Alignof(A{}) = 8,即三个变量成员的最大值,内存对齐需要保证该结构体的内存占用是 8 的整数倍,当前内存占用是 20个字节,因此需要再补充4个字节:
    在这里插入图片描述

  3. 最终该结构体的内存占用为 24字节。

type B struct {a int32b int32c int64
}func main() {fmt.Println(unsafe.Sizeof(B{1, 1, 1}))  // 16
}
  1. 第一个字段是 int32 类型,unsafe.Sizeof(int32(1))=4,内存占用为4个字节,同时unsafe.Alignof(int32(1)) = 4,内存对齐需保证变量首地址可以被4整除,我们假设地址从0开始,0可以被4整除:
    在这里插入图片描述

  2. 第二个字段是 int32 类型,unsafe.Sizeof(int32(1))=4,内存占用为4个字节,同时unsafe.Alignof(int32(1)) = 4,内存对齐需保证变量首地址可以被4整除,当前地址为4,4可以被4整除:
    在这里插入图片描述

  3. 第三个字段是 int64 类型,unsafe.Sizeof(int64(1))=8,内存占用为8个字节,同时unsafe.Alignof(int64(1)) = 8,内存对齐需保证变量首地址可以被8整除,当前地址为8,8可以被8整除:
    在这里插入图片描述

  4. 所有成员对齐都已经完成,现在我们需要看一下整体对齐规则:unsafe.Alignof(B{}) = 8,即三个变量成员的最大值,内存对齐需要保证该结构体的内存占用是 8 的整数倍,当前内存占用是 16个字节,已经符合规则,最终该结构体的内存占用为 16个字节。

空结构体对齐规则

如果空结构体作为结构体的内置字段:当变量位于结构体的前面和中间时,不会占用内存;当该变量位于结构体的末尾位置时,需要进行内存对齐,内存占用大小和前一个变量的大小保持一致。

type C struct {a struct{}b int64c int64
}type D struct {a int64b struct{}c int64
}type E struct {a int64b int64c struct{}
}type F struct {a int32b int32c struct{}
}func main() {fmt.Println(unsafe.Sizeof(C{})) // 16fmt.Println(unsafe.Sizeof(D{})) // 16fmt.Println(unsafe.Sizeof(E{})) // 24fmt.Println(unsafe.Sizeof(F{})) // 12
}

参考:https://juejin.cn/post/7077833959047954463

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器视觉-硬件

机器视觉-硬件 镜头焦距凸透镜焦点不止一个相机镜头由多个镜片组成对焦和变焦 镜头光圈光圈的位置光圈系数F 镜头的景深景深在光路中的几何意义 远心镜头远心镜头的种类远心镜头特性应用场景 镜头的分辨率镜头反差镜头的MTF曲线镜头的靶面尺寸镜头的几何相差相机镜头接口螺纹接…

个人手里有一批宽带资源,想跑PCDN 如何做?

网友问我手里有一批宽带资源,想要跑PCDN该如何做,可以按照以下步骤操作: 了解PCDN的基本原理和市场需求。PCDN(Peer-to-Content Delivery Network)是一种基于P2P技术的内容分发网络,通过将用户设备上的空闲…

javas-core VS java-object-diff

对照工具选择 javas-core 和 java-object-diff ,对比demo https://github.com/kofgame/objectdiff-vs-javers,都为同源对比,都支持嵌套对象。 使用JMH测试方法进行性能测试,使用题库的QuestionResponseVO对象来进行对照对比,进行…

【Python搞定车载自动化测试】——Python基于Pytest框架实现UDS诊断自动化(含Python源码)

系列文章目录 【Python搞定车载自动化测试】系列文章目录汇总 文章目录 系列文章目录💯💯💯 前言💯💯💯一、环境搭建1.软件环境2.硬件环境 二、目录结构三、源码展示1.诊断基础函数方法2.诊断业务函数方法…

深入探索Python基础:两个至关重要的函数

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、初学者的基石:print与input函数 二、类型转换:从字符串到浮点数…

【完整解析】2024电工杯数学建模A题论文与代码

园区微电网风光储协调优化配置 1 论文2 代码分享2.1 第三题第一问 3 数据与代码 1 论文 2 代码分享 2.1 第三题第一问 function anssq3w1ObjFun(ttt,id); %ttttt(1); tt[750,0,0,1000,600,500]; limttt(1)*200; limmttt(2)*500*0.9-ttt(2)*500*0.1; t1ttt(3)*1000;t2ttt(4)*1…

ASP+ACCESS多功能论坛程序设计

摘 要 随着计算机的广泛应用,人们已经对网络不再感到陌生。在科技飞速发展的今天,电脑信息技术与各行各业进行了有效的结合。人们在网上可以进行网上购物,网上交友,电子商务,网络营效等等。面对强大的网络功能&#x…

通过Kafka-Logger插件收集流量进行漏洞扫描

通过Kafka-Logger插件收集流量进行漏洞扫描 方案 可以通过APISIX kafka-logger 插件将日志作为 JSON 对象推送到 Apache Kafka 集群中,消费Kafka里的数据格式化后添加到MySQL。 方案详情 1、登录APISIX,启用内置的kafka-logger 插件: 2…

从 0 实现一个文件搜索工具 (Java 项目)

背景 各文件系统下, 都有提供文件查找的功能, 但是一般而言搜索速度很慢 本项目仿照 everything 工具, 实现本地文件的快速搜索 实现功能 选择指定本地目录, 根据输入的信息, 进行搜索, 显示指定目录下的匹配文件信息文件夹包含中文时, 支持汉语拼音搜索 (全拼 / 首字母匹配…

DiffMap:首个利用LDM来增强高精地图构建的网络

论文标题: DiffMap: Enhancing Map Segmentation with Map Prior Using Diffusion Model 论文作者: Peijin Jia, Tuopu Wen, Ziang Luo, Mengmeng Yang, Kun Jiang, Zhiquan Lei, Xuewei Tang, Ziyuan Liu, Le Cui, Kehua Sheng, Bo Zhang, Diange Ya…

解决go install 网络问题

rootiZbp1hiqzlhh6w05gloffgZ:~# go install mvdan.cc/garblelatest go: mvdan.cc/garblelatest: module mvdan.cc/garble: Get "https://proxy.golang.org/mvdan.cc/garble/v/list": dial tcp 172.217.160.81:443: i/o timeout解决方法 更换阿里代理 rootiZbp1hiq…

浅论未来 IT 和财务结合的趋势

前言 会计核算企业各类业务单据,所有业务部门的数据都会汇流到财务部来,所以会计其实是企业的数据中心;而 IT 技术正是处理数据的利器,可以将重复的流程自动化,还能将财务数据可视化;因此,两者…

SPI通信(STM32)

一、SPI通信 1、SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线 2、四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MIS…

esp32-idf 开发踩坑记录

现象 直接使用原始命令编译idf.py build 但是提示idf 版本错误 卸载旧版本 编译出错build 问题 然后删除编译文件后,重新编译,还是出错 解决方法1 最后发现是因为项目所在文件夹有中文目录,把项目迁移到英文目录后,重新编译&a…

打破传统相亲模式,这几款靠谱的相亲软件助你脱单

相亲软件在当今社会已经变得越来越普遍,市面上有众多相亲软件可供选择,但哪些相亲软件好用呢?下面介绍几款备受好评的相亲软件,帮助你在茫茫人海中找到那个对的人! 1、一伴婚恋 这个APP它最大的优点就是信息真实靠谱…

Filter和Interceptor

会话 cookie 服务器自动将cookie响应给浏览器 浏览器接收响应回来的数据 自动将cookie存储在本地, 后续请求当中浏览器将cookie携带到服务器 cookie不能跨域,存储在客户端 session 存储在服务器 token------>JWT 存储在客户端, 服务…

【C++ QT项目实战-03】---- C++ QT系统实现读取JSON文件数据的自动化模式

🎩 欢迎来到技术探索的奇幻世界👨‍💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介:C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &#…

Flink 窗口

窗口(Window) 窗口是处理无限流的核心。 窗口将流分割成有限大小的“桶”,我们可以计算窗口中的数据。 窗口程序一般有键控流(keyed streams)的窗口程序 和 非键控流(non-keyed streams)的窗口…

Rabbitmq 搭建使用案例 [附源码]

Rabbitmq 搭建使用案例 文章目录 RabbitMQ搭建docker 代码golang生产者消费者 可视化消费进度 RabbitMQ搭建 docker docker run -d --hostname rabbitmq --name rabbitmq -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASSadmin -e RABBITMQ_DEFAULT_VHOSTmy_vhost -e…

LeetCode/NowCoder-复杂度OJ练习

无论你觉得自己多么的不幸,永远有人比你更加不幸。💓💓💓 目录 说在前面 题目一:消失的数字 题目二:轮转数组 SUMUP结尾 说在前面 dear朋友们大家好!💖💖&#x1f496…