golang内存对齐
为什么要内存对齐?
CPU访问内存时,以CPU的位数为单位进行访问。
如果访问未对齐的内存,处理器需要做两次内存访问,对齐的内存的访问可能仅需要一次,利用内存对齐后提升读取速度。
golang结构体内存对齐规则
在代码编译阶段,编译器会对数据的存储布局进行对齐优化。
对于golang结构体来说,在编译后,就已经确定好了结构体的大小以及各成员相对首部的偏移量。
如下两个结构体T1和T2,成员变量相同,但是成员位置不同
type T1 struct {a int8b int64c int16
}type T2 struct {a int8c int16b int64
}func TestAlign(t *testing.T) {var u1 T1var u2 T2println(unsafe.Sizeof(u1)) // 24println(unsafe.Sizeof(u2)) // 16
}
打印内存地址
u1->a的地址 0xc0002d7e40 // 占用一个字节
u1->b的地址 0xc0002d7e48 // 占用两个字节,前面填充一个字节
u1->c的地址 0xc0002d7e50 // 占用八个字节,前面填充四个字节u2->a的地址 0xc0002d7e30 // 占用一个字节
u2->c的地址 0xc0002d7e32 // 占用两个字节,前面填充一个字节
u2->b的地址 0xc0002d7e38 // 占用八个字节,前面填充四个字节
在64位机器上执行,T2的结构体内存对齐为如下所示:
规则
结构成员需要对齐
第一个的成员相对于结构体首地址的offset = 0
非第一个成员相对于结构体首地址的 offset = min(该成员大小, 对齐值)*N倍
如有需要,编译器会在成员间加上填充字节
结构体间需要对齐
结构体的长度 = 成员中最大对齐值 * M倍
示例
bool大小占用1B,对齐值为1B
int32大小占用4B,对齐值为4B
int64大小占用8B,对齐值为8B
string大小占用16B,对齐值为8B
complex128大小占用16B,对齐值为8B// 结构体的总大小为:max(1, 8, 1) * 4 = 32
type T1 struct {a bool // 0xc000042750,offset=0,占用1字节b complex128 // 0xc000042758,offset=min(16,8)*1 = 8,占用16字节c bool // 0xc000042768,offset=min(1,1)*24 = 24,占用1字节
}// 结构体的总大小为:max(8, 1) * 3 = 24
type T2 struct {a complex128 // offset=0,占用16字节b bool // offset=min(1,1)*16 = 16,占用1字节
}// 结构体的总大小为:max(1, 2) * 2 = 4
type T3 struct {a bool // offset=0,占用1字节b int16 // offset=min(2,2)*1 = 2,占用2字节
}
特殊字段的内存对齐
空结构体被广泛作为各种场景下的占位符使用。一是节省资源(比如利用map实现set),二是空结构体本身就具备很强的语义。
type T1 struct {a struct{}b bool
}type T2 struct {a boolb struct{}
}func main() {var u1 T1println(unsafe.Sizeof(u1)) // 1println("u1->a的地址", &u1.a) // 0xc00004276dprintln("u1->b的地址", &u1.b) // 0xc00004276dvar u2 T2println(unsafe.Sizeof(u2)) // 2println("u2->a的地址", &u2.a) // 0xc00004276eprintln("u2->b的地址", &u2.b) // 0xc00004276f
}
空结构体字段放最后会额外占用1B内存,放在非最后位置不占用内存。
原因:
当空结构体字段定义到最后时,因为如果有指针指向该字段,返回的地址将在结构体之外,如果此指针一直存活不释放对应的内存,就会有内存泄露的问题(该内存不因结构体释放而释放)。
Hot path
hot path 是指执行非常频繁的指令序列。
访问结构体的第一个字段时,可以直接使用结构体的指针来访问第一个字段。
访问结构体的其他字段,除了结构体指针外,还需要计算偏移量。
在机器码中,偏移量是随指令传递的附加值,带上偏移量的指令序列会更长。同时CPU 还需要做一次偏移量与指针的加法运算,才能获取要访问的值的实际地址。
因此,访问第一个字段与访问其它字段相比,机器代码会更紧凑(长度短),执行速度也会更快(没有指针与偏移量的加法运算)。
示例
// sync.once中,官方解释可见英文,done使用很频繁,所以被放在结构体第一位
type Once struct {// done indicates whether the action has been performed.// It is first in the struct because it is used in the hot path.// The hot path is inlined at every call site.// Placing done first allows more compact instructions on some architectures (amd64/x86),// and fewer instructions (to calculate offset) on other architectures.done uint32m Mutex
}
总结
- 定义结构体时可以把类型相同的字段定义放一块,同时按照占用空间从小到大(或者从大到小)的顺序定义字段。
- 结构体内嵌套空结构体时,不要放在最后一位。
- 定义结构体时,可以考虑把常使用的字段放在第一位。
相关文章:

golang内存对齐
为什么要内存对齐? CPU访问内存时,以CPU的位数为单位进行访问。 如果访问未对齐的内存,处理器需要做两次内存访问,对齐的内存的访问可能仅需要一次,利用内存对齐后提升读取速度。 golang结构体内存对齐规则 在代码编译…...

【CheatSheet】Python、R、Julia数据科学编程极简入门
《Python、R、Julia数据科学编程极简入门》PDF版,是我和小伙伴一起整理的备忘清单,帮助大家10分钟快速入门数据科学编程。 另外,最近 TIOBE 公布了 2023 年 8 月的编程语言排行榜。 Julia 在本月榜单中实现历史性突破,成功跻身 …...

【golang】怎样判断一个变量的类型?
怎样判断一个变量的类型? package mainimport "fmt"var container []string{"zero", "one", "two"} func main() {container : map[int]string{0: "zero", 1: "one", 2: "two"}fmt.Printf…...

怎么学习AJAX相关技术? - 易智编译EaseEditing
学习AJAX(Asynchronous JavaScript and XML)相关技术可以让你实现网页的异步数据交互,提升用户体验。以下是一些学习AJAX技术的步骤和资源: HTML、CSS和JavaScript基础: 首先,确保你已经掌握了基本的HTML…...

JDK、JRE、JVM:揭秘Java的关键三者关系
文章目录 JDK:Java开发工具包JRE:Java运行环境JVM:Java虚拟机关系概述 案例示例:Hello World结语 在Java世界中,你可能经常听到JDK、JRE和JVM这几个概念,它们分别代表了Java开发工具包、Java运行环境和Java…...
【reactNative混合安卓开发~使用问题持续更】
reactNative混合安卓开发 reactNative开发移动端reactNative界面开发前端init.bat文件部分组件第三方组件解析1、定义theme主题shopify/restyle;菜单导航react-navigation/drawer、react-navigation/native; RN问题记录1、使用theme.js写的公共组件报错&…...

OCR的发明人是谁?
OCR的发明背景可以追溯到早期计算机科学和图像处理的研究。随着计算机技术的不断发展,人们开始探索如何将印刷体文字转换为机器可读的文本。 OCR(Optical Character Recognition,光学字符识别)的发明涉及多个人的贡献,…...
笔记本电脑连上WiFi之后的IP为什么会变?如何让它不变固定住?
笔记本连上WiFi后获取IP地址的过程,通常是通过DHCP (动态主机配置协议) 来完成的。默认情况下,DHCP会根据连接设备和网络状态动态地分配IP地址,因此你会看到IP地址可能经常改变。 如果你希望电脑的IP地址固定,可以尝试设置静态IP…...

【数学建模】--因子分析模型
因子分析有斯皮尔曼在1904年首次提出,其在某种程度上可以被看成时主成分分析的推广和扩展。 因子分析法通过研究变量间的相关稀疏矩阵,把这些变量间错综复杂的关系归结成少数几个综合因子,由于归结出的因子个数少于原始变量的个数,…...

RAM不够?CUBEIDE使用CCMRAM
RAM不够?使用CCMRAM 文章目录 RAM不够?使用CCMRAM打开连接LD文件:添加代码添加标识宏使用 打开连接LD文件: 添加代码 在SECTIONS段最后加上下面代码: _siccmram LOADADDR(.ccmram); /* CCM-RAM section * * IMPORTAN…...

npm ERR! code ERESOLVEnpm ERR! ERESOLVE unable to resolve dependency tree
拉取项目到本地 执行 npm install 报错 遇到这个问题首先确认的就是版本是不是太高了,降一下版本。或者通过yarn命令替代npm install命令安装,同理,启动也可以采用yarn dev 启动代替npm run dev 下面教大家用一个NVM工具,这个工…...

使用 prometheus client SDK 暴露指标
目录 1. 使用 prometheus client SDK 暴露指标1.1. How Go exposition works1.2. Adding your own metrics1.3. Other Go client features 2. Golang Application monitoring using Prometheus2.1. Metrics and Labels2.2. Metrics Types2.2.1. Counters:2.2.2. Gauges:2.2.3. …...
Jmeter之BeanShell取出参数进行四则运算,并判断是否正确
首先调用余额接口,使用正则提取响应中的余额字段,记作变量acctBal1做支付交易再次调用余额接口,使用正则提取响应中的余额字段,记作变量acctBal2最后在结果树中可以看到断言错误的信息,断言正确时没有提示以下是beansh…...
PYTHON 斗地主发牌 (简易版)
利用方法: 1. random.randint( ) 随机抽取数字 方法 2.random.sample((抽取范围的参数),(抽取的个数)) 返回的是列表 所以用[0]可以输出里面的元素 import random# 1. 创建牌 # 花色 color ["\u2660", "\u2663", "\u2665", "\…...
CSS文本裁剪
对于单行文本裁剪: span {text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block; } 对于多行文本裁剪: 在文本容器上定义 CSS Flexbox 属性 display: -webkit-box; 定义要显示的文本行数 -webkit-line-clamp: 4; 添加 -webkit-…...
ClickHouse常见的引擎和使用
1.日志引擎 日志引擎特点 1.数据存储在磁盘上 2.写入时将数据追加在文件末尾 3.不支持突变操作 4.不支持索引 5.非原子地写入数据 6.引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作 建表语法示例 CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( …...

构建之法 - 软件工程实践教学:一线教师的13问
福州大学单红老师的软工课程总结 2020春,不一样的学期不一样的软工实践 单红⽼师在总结中,提出了13条疑惑,《构建之法》的作者邹欣⽼师就单红⽼师提出的每⼀条疑惑,给出了⾃⼰的思考,与他进⾏探讨交流。欢迎你也来参与…...
联调 matlab 遇到的一些事儿
记录当时遇到的问题,因为平时不写 matlab,所以没有深入的理解。 版本兼容 当时遇到的第一个问题就是不同版本 matlab 带来的兼容性问题。同时开发使用的是 2021a 版本,而调试时使用的是 2022b 版本。在新版本中某些函数已被弃用,…...

时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型
文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 1.Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 2.单变量时间序列预测; 3.多指标评价,评价指标包括:R2、MAE、MBE等,代码质量极高…...

3.2 Tomcat基础
1. Tomcat概述 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器。 Tomcat版本:apache-tomcat-8.5.76。 2.IDEA集成Tomcat 第一步 第二步 第三步 编辑切换为居中 添加图片注释,不超过 140 字࿰…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...