内存对齐对性能的影响

news/2024/5/18 21:45:38/文章来源:https://blog.csdn.net/General_zy/article/details/127135453

计算字节数

在 Go 语言中,可以使用 unsafe.Sizeof 计算出一个数据类型实例需要占用的字节数。

package mainimport ("fmt""unsafe"
)type Args struct {num1 intnum2 int
}type Flag struct {num1 int16num2 int32
}func main() {fmt.Println(unsafe.Sizeof(Args{}))fmt.Println(unsafe.Sizeof(Flag{}))
}

在这里插入图片描述

  1. Args 由 2 个 int 类型的字段构成,在 64位机器上,一个 int 占 8 字节,因此存储一个 Args 实例需要 16 字节。
  2. Flag 由一个 int32 和 一个 int16 的字段构成,成员变量占据的字节数为 4+2 = 6,但是 unsafe.Sizeof 返回的结果为 8 字节,多出来的 2 字节是内存对齐的结果。

因此,一个结构体实例所占据的空间等于各字段占据空间之和,再加上内存对齐的空间大小。

内存对齐

  1. CPU 只从对齐的地址开始加载数据

  2. CPU 读取块的大小是固定的,通常为 B 的 2 的整数幂次

  3. CPU 访问内存时,并不是逐个字节访问,而是以字长(word size)为单位访问。比如 32 位的 CPU ,字长为 4 字节,那么 CPU 访问内存的单位也是 4 字节。

  4. 这么设计的目的,是减少 CPU 访问内存的次数,加大 CPU 访问内存的吞吐量。比如同样读取 8 个字节的数据,一次读取 4 个字节那么只需要读取 2 次。

  5. CPU 始终以字长访问内存,如果不进行内存对齐,很可能增加 CPU 访问内存的次数。

在这里插入图片描述
6. 变量 a、b 各占据 3 字节的空间,内存对齐后,a、b 占据 4 字节空间,CPU 读取 b 变量的值只需要进行一次内存访问。
7. 如果不进行内存对齐,CPU 读取 b 变量的值需要进行 2 次内存访问。第一次访问得到 b 变量的第 1 个字节,第二次访问得到 b 变量的后两个字节。

结论:内存对齐对实现变量的原子性操作也是有好处的,每次内存访问是原子的,如果变量的大小不超过字长,那么内存对齐后,对该变量的访问就是原子的,这个特性在并发场景下至关重要。

对齐系数

unsafe 标准库提供了 Alignof 方法,可以返回一个类型的对齐值,也可以叫做对齐系数或者对齐倍数。

unsafe.Alignof(Args{}) // 8
unsafe.Alignof(Flag{}) // 4
  1. 对于任意类型的变量 x ,unsafe.Alignof(x) 至少为 1。
  2. 对于 struct 结构体类型的变量 x,计算 x 每一个字段 f 的 unsafe.Alignof(x.f),unsafe.Alignof(x) 等于其中的最大值。
  3. 对于 array 数组类型的变量 x,unsafe.Alignof(x) 等于构成数组的元素类型的对齐倍数。
  4. 没有任何字段的空 struct{} 和没有任何元素的 array 占据的内存空间大小为 0,不同的大小为 0 的变量可能指向同一块地址。

struct 内存对齐

type demo1 struct {a int8b int16c int32
}type demo2 struct {a int8c int32b int16
}func main() {fmt.Println(unsafe.Sizeof(demo1{})) // 8fmt.Println(unsafe.Sizeof(demo2{})) // 12
}

demo1:

  1. a 是第一个字段,默认是已经对齐的,从第 0 个位置开始占据 1 字节。
  2. b 是第二个字段,对齐倍数为 2,因此,必须空出 1 个字节,偏移量才是 2 的倍数,从第 2 个位置开始占据 2 字节。
  3. c 是第三个字段,对齐倍数为 4,此时,内存已经是对齐的,从第 4 个位置开始占据 4 字节即可。

因此 demo1 的内存占用为 8 字节。

在这里插入图片描述

demo2:

  1. a 是第一个字段,默认是已经对齐的,从第 0 个位置开始占据 1 字节。
  2. c 是第二个字段,对齐倍数为 4,因此,必须空出 3 个字节,偏移量才是 4 的倍数,从第 4 个位置开始占据 4 字节。
  3. b 是第三个字段,对齐倍数为 2,从第 8 个位置开始占据 2 字节,但最大对齐倍数为4,需要填充2个字节

demo2 的对齐倍数由 c 的对齐倍数决定,也是 4,因此,demo2 的内存占用为 12 字节。

在这里插入图片描述

空结构体

空 struct{} 大小为 0,作为其他 struct 的字段时,一般不需要内存对齐。
但是有一种情况除外:即当 struct{} 作为结构体最后一个字段时,需要内存对齐。

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

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

相关文章

浅析axios原理与使用(包括axios的优雅写法与res的解构赋值)

目录前言一,什么是axios二,axios的基本使用2.1 不含参的axios调用2.2 含参数的axios调用三,axios的原理(拦截器)3.1 客户端与服务器之间的交互原理(复习可略过)3.2 浅析axios原理四,…

西瓜书研读——第三章 线性模型: 线性判别分析 LDA

西瓜书研读系列: 西瓜书研读——第三章 线性模型:一元线性回归 西瓜书研读——第三章 线性模型:多元线性回归 西瓜书研读——第三章 线性模型:线性几率回归(逻辑回归) 主要教材为西瓜书,结合…

K8s存储与GlusterFS实战

一、存储概述 1、共享存储机制概述 Kubernetes对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后…

常见的垃圾回收机制

如何工作在某些 Java 虚拟机中,堆的实现截然不同:它更像一个传送带,每分配一个新对象,它就向前移动一格。 这意味着对象存储空间的分配速度特别快。Java 的"堆指针"只是简单地移动到尚未分配的区域,所以它的效率与 C++ 在栈上分配空间的效率相当垃圾回收器工作时…

将Springbooot项目部署到云服务器上运行

将Springbooot项目部署到云服务器上运行一、项目打包二、将结果jar文件上传服务器三、授予jar文件权限,并运行四、运行失败可能原因一、项目打包 File->Project Structure Project Settings -> Artifacts -> 点击 号 -> JAR -> From modules with d…

Linux-常见命令(三)

前言 作者:小蜗牛向前冲 名言:我可以接收失败,但我不能接收放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 find指令&…

2022-2023-1 20221318 《计算机基础和程序设计》第五周学习总结

作业信息 这个作业属于那个班级 https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP 作业要求 https://www.cnblogs.com/rocedu/p/9577842.html#WEEK03 作业目标 学习《计算机科学概论》的第6章 《程序设计》第4章 作业正文 https://i.cnblogs.com/posts/edit;postId=1673…

JavaScript:DOM

目录 一、DOM介绍 1、节点和节点的关系 2、获取页面中的元素可以使用以下几种方式 3、鼠标点击事件 4、访问节点 5、获取元素的样式 一、DOM介绍 DOM:Document Object Model(文档对象模型) DOM是W3C组织推荐的处理可扩展标记语言的标…

数据结构线性表

目录 2.1 线性表的基本概念 2.2 线性表的顺序表示 2.3 线性表的链式表示 2.3.1 单链表 2.3.2 循环单链表 2.3.3 双向链表 2.3.4 双向循环链表 2.3.5 静态链表 牢固掌握线性表在两种存储结构下的各种基本操作,牢记各种算法思想 2.1 线性表的基本概念 Def&a…

Linux 学习 -- 容器技术

Linux 学习 – 容器技术 容器基础概述容器部署 一、容器基础概述 容器(Container) : 定义:指的是针对应用所需的运行环境资源(依赖库/目录/网络/用户……等)进行整体封装的技术。 特点:封装好的镜像相比虚拟机的粒度要更细&…

类与对象(十八)----super关键字

super关键字 super代表父类的引用,可以用于访问父类的属性,方法,构造器。 super使用 使用super访问父类的属性:权限内的才可以访问。使用语法----super.属性名 public class A {public int n1 12;protected int n2 12;int n…

程序员的数学课10 信息熵:事件的不确定性如何计算?

你好,欢迎来到第 10 课时——信息熵:事件的不确定性如何计算? 从加乘法则开始,我们基于事情的不确定性出发,尝试计算事情发生的可能性。然而,对于事件与事件之间的不确定性如何相比和衡量,单独…

iOS 16 中 SwiftUI 防止弹出的 sheet 视图被下滑关闭(dismiss)的新解决方案

功能需求 在SwiftUI中,我们往往需要只通过代码控制 sheet 弹出视图的关闭(dismiss),而禁止用户手动下滑关闭弹出的视图。 如上图所示,在 iOS 16 中 App 弹出的 sheet 视图只允许点击按钮关闭(dismiss),而用户无法通过下滑来关闭它。 我们之前在 SwiftUI禁止用户关闭s…

【图灵MySQL】Explain详解与索引最佳实践

Explain使用与详解 前期准备 在开始之前,我们先准备一下所需要的数据,创建3个表——actor、film、film_actor actor 表 只有一个主键 CREATE TABLE actor (id int(11) NOT NULL,name varchar(45) DEFAULT NULL,update_time datetime DEFAULT NULL,P…

PTA前三次作业总结分析——BLOG_1

PTA第一次大作业 前言:第一次的大作业比较的简单,没有涉及到类的设计,只要在主类中的主函数实现其相应功能。此次作业主要考察的还是我们对于输入输出的应用和基本判断,double 类型数据强制转换为float类型数据输出,以及循环语句的使用和string类的数据处理。虽然这些题目的…

JDK1.8的File类详解

1、静态属性 后面带Char的是转为char类型,其实都是一样的结果。 为什么要单独把地址的特殊字符单独包装为静态类呢 因为在windows系统中,两个地址中间用分号[;]隔开,像环境变量中的path的内容。 但是在Linux系统中,两个地址中间是…

计算机网络——应用层网络应用模型、DNS系统、文件传输协议、电子邮件、万维网和HTTP协议

文章目录前言一、网络应用模型1、应用层概述2、客户服务器模型3、P2P 模型二、DNS 系统1、域名2、域名服务器三、文件传输协议四、电子邮件1、简单结构2、简单邮件传送协议(SMTP)3、邮局协议(POP3)和网际报文存取协议(IMAP)五、万维网和 HTTP 协议1、万维网概述2、超文本传输协…

LeGO-LOAM(1):运行LeGO-LOAM

目录 # 1 安装与编译 ## 1.1 依赖项 ### 1.1.1 ros ### 1.1.2 gtsam ## 1.2 编译 # 2 系统介绍 # 3 运行demo ### 3.1 数据下载 ### 3.2 数据描述 ### 3.3 demo运行 ####(1)运行launch文件 ####(2)播放数据文件 ####…

基于Java+SpringBoot+Thymeleaf+Mysql新冠疫苗预约系统设计与实现

项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于web网页的新冠疫苗预约系统,整个网站项目使用了B/S架构,基于java的springboot框架下开发;;通过后台设置医院信息、录入医院科室信息、录入医生信息、设置医…

OpenDataV低代码平台增加自定义属性编辑

上一篇我们讲到了怎么在OpenDataV中添加自己的组件,为了让大家更快的上手我们的平台,这一次针对自定义属性编辑,我们再来加一篇说明。我们先来看一下OpenDataV中的属性编辑功能。 20221001202917当我们拖动一个组件到画布中以后,点…