当前位置: 首页 > news >正文

【iOS】——内存对齐

内存对齐是什么

内存对齐指的是数据在内存中的布局方式,它确保每个数据类型的起始地址能够满足该类型对齐的要求。这是因为现代处理器在访问内存时,如果数据的起始地址能够对齐到一定的边界,那么访问速度会更快。这种对齐通常是基于数据类型大小的倍数。内存对齐包括两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐。

内存对齐的原因

内存对齐的主要原因有两个:性能和硬件限制。

性能原因

  1. 硬件访问效率:现代处理器设计为能够更高效地访问对齐的数据。这是因为处理器内部的总线宽度和寄存器大小通常决定了数据的最佳访问粒度。例如,如果一个处理器的寄存器大小是64位,那么访问64位对齐的长整型数据会比访问未对齐的数据更快,因为后者可能需要多次内存访问才能装载完整数据。
  2. 缓存性能:现代处理器使用多层次的缓存(L1, L2, L3等)来提高数据访问速度。数据对齐有助于缓存行的高效使用,减少缓存未命中,从而提高整体性能。
  3. 并发访问:在多核或多处理器系统中,对齐数据可以减少访问冲突,因为每个处理器或核心可以更有效地访问自己负责的内存区域。

硬件限制

  1. 硬件异常:某些硬件平台可能无法访问未对齐的内存地址,访问未对齐数据可能导致硬件异常或陷阱,这会极大地降低程序的性能,甚至导致程序崩溃。
  2. 字节序问题:虽然内存对齐与字节序(endianness)直接关联不大,但在处理字节序敏感的数据时,对齐可以避免额外的字节交换操作,从而提高性能。

内存对齐原则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。在ios中,Xcode默认为#pragma pack(8),即8字节对齐

  1. 数据成员对齐原则

    • 结构体的第一个数据成员放置在offset为0的位置。

    • 后续的数据成员将被放置在它们各自自然对齐的地址上,即如果成员是4字节的整型,它将被放置在4字节对齐的位置;如果是8字节的双精度浮点型,它将被放置在8字节对齐的位置。

  2. 结构体总大小对齐原则

    • 结构体的总大小必须是其内部最大成员大小的整数倍。如果结构体的自然大小不符合这个条件,编译器会在最后一个成员之后填充一些额外的字节,直到整个结构体的大小满足对齐要求。
  3. 自然边界对齐原则:: 每种数据类型都有一个“自然”边界,这是指数据类型大小的整数倍地址。例如,一个int类型在32位系统中通常占用4个字节,因此它应该在地址能够被4整除的位置开始。同样,一个short类型(通常2个字节)应该在能够被2整除的地址开始,以此类推。

在这里插入图片描述

可以将内存对齐原则可以理解为以下几点:

  • 【原则一】 数据成员的对齐规则可以理解为min(m, n) 的公式, 其中 m表示当前成员的开始位置, n表示当前成员所需要的位数。如果满足条件 m 整除 n (即 m % n == 0), nm 位置开始存储, 反之继续检查 m+1 能否整除 n, 直到可以整除, 从而就确定了当前成员的开始位置。
  • 【原则二】数据成员为结构体:当结构体嵌套了结构体时,作为数据成员的结构体的自身长度作为外部结构体的最大成员的内存大小,比如结构体a嵌套结构体b,b中有char、int、double等,则b的自身长度为8
  • 【原则三】最后结构体的内存大小必须是结构体中最大成员内存大小的整数倍,不足的需要补齐。

下面举个例子:

struct Example {char c;int i;double d;
};

char的大小为1字节,int的大小为4字节,而double的大小为8字节。由于double是最大的成员,所以整个结构体的大小必须是8字节的倍数。char会放在offset为0的位置,int会放在offset为4的位置(因为它需要4字节对齐),而double会放在offset为8的位置(因为它需要8字节对齐)。由于double之后没有更多的成员,所以结构体的大小就刚好是16字节,正好是8字节的倍数。

结构体嵌套的对齐

当结构体嵌套其他结构体时,不仅要考虑单个成员的对齐,还要考虑嵌套结构体本身的对齐和整个复合结构体的对齐。

遵循以下原则:

  • 嵌套的结构体成员将被视为一个单一的整体,其对齐需求基于嵌套结构体中最大成员的对齐需求。
  • 如果嵌套的结构体中有自己的对齐需求(比如含有double类型),那么在外部结构体中,嵌套结构体将按照其内部最大成员的对齐需求进行对齐。
  • 外部结构体的对齐取决于其所有成员(包括嵌套结构体)的最大对齐需求。
  • 如果嵌套结构体的对齐需求大于外部结构体中任何其他成员的对齐需求,那么整个外部结构体将按照嵌套结构体的对齐需求对齐。
  • 当嵌套结构体不符合其对齐需求时,编译器会在嵌套结构体之前插入填充字节。嵌套结构体结束后的下一个成员需要更大的对齐,编译器会在嵌套结构体之后插入填充字节。
  • 整个结构体的大小也必须满足结构体中最大成员的对齐需求。如果结构体的自然大小不满足这一要求,编译器会在结构体末尾添加额外的填充字节。

获取内存大小的方式

获取内存大小的三种方式分别是:

  • sizeof
  • class_getInstanceSize
  • malloc_size
sizeof

1、sizeof是一个操作符,不是函数

2、我们一般用sizeof计算内存大小时,传入的主要对象是数据类型,这个在编译器的编译阶段(即编译时)就会确定大小而不是在运行时确定。

3、sizeof最终得到的结果是该数据类型占用空间的大小

class_getInstanceSize

这个方法是runtime提供的api,用于获取类的实例对象所占用的内存大小,并返回具体的字节数,其本质就是获取实例对象中成员变量的内存大小。采用8字节对齐,参照的对象的属性内存大小

malloc_size

这个函数是获取系统实际分配的内存大小。采用16字节对齐,参照的整个对象的内存大小,对象实际分配的内存大小必须是16的整数倍

目前已知的16字节内存对齐算法有两种

  • alloc源码分析中的align16
  • malloc源码分析中的segregated_size_to_fit

下面举个例子:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>int main(int argc, const char * argv[]) {@autoreleasepool {NSObject *objc = [[NSObject alloc] init];NSLog(@"objc对象类型占用的内存大小:%lu",sizeof(objc));NSLog(@"objc对象实际占用的内存大小:%lu",class_getInstanceSize([objc class]));NSLog(@"objc对象实际分配的内存大小:%lu",malloc_size((__bridge const void*)(objc)));}return 0;
}

在这里插入图片描述

内存优化(属性重排)

结构体内存大小与结构体成员内存大小的顺序有关:

如果是结构体中数据成员是根据内存从小到大的顺序定义的,根据内存对齐规则来计算结构体内存大小,需要增加有较大的内存padding即内存占位符,才能满足内存对齐规则,比较浪费内存

如果是结构体中数据成员是根据内存从大到小的顺序定义的,根据内存对齐规则来计算结构体内存大小,我们只需要补齐少量内存padding即可满足堆存对齐规则,这种方式就是苹果中采用的,利用空间换时间,将类中的属性进行重排,来达到优化内存的目的

在字节对齐算法中,对齐的主要是对象,对象的本质是objc_object结构体。

对于一个对象来说,其真正的对齐方式8字节对齐,8字节对齐已经足够满足对象的需求了

apple系统为了防止一切的容错,采用的是16字节对齐的内存,主要是因为采用8字节对齐时,两个对象的内存会紧挨着,显得比较紧凑,而16字节比较宽松,利于苹果以后的扩展。

相关文章:

【iOS】——内存对齐

内存对齐是什么 内存对齐指的是数据在内存中的布局方式&#xff0c;它确保每个数据类型的起始地址能够满足该类型对齐的要求。这是因为现代处理器在访问内存时&#xff0c;如果数据的起始地址能够对齐到一定的边界&#xff0c;那么访问速度会更快。这种对齐通常是基于数据类型…...

网络安全-网络安全及其防护措施10

46.软件定义网络&#xff08;SDN&#xff09; 软件定义网络&#xff08;SDN&#xff09;的概念和特点 软件定义网络&#xff08;SDN&#xff09;是一种新兴的网络架构&#xff0c;通过将网络的控制平面&#xff08;Control Plane&#xff09;和数据转发平面&#xff08;Data …...

Pytorch基础应用

1.数据加载 1.1 读取文本文件 方法一&#xff1a;使用 open() 函数和 read() 方法 # 打开文件并读取全部内容 file_path example.txt # 替换为你的文件路径 with open(file_path, r) as file:content file.read()print(content)方法二&#xff1a;逐行读取文件内容 # 逐…...

Axure 教程 | 设置文本框背景透明

​在AXURE软件中&#xff0c;部件样式可以编辑&#xff0c;但有时却无法满足所有个性化原型的需求。例如文本框部件&#xff0c;可以设置是否隐藏边框&#xff0c;但即使隐藏边框之后&#xff0c;文本框还会有白色的背景。 当界面需要一个无背景色的输入框时&#xff0c;对于完…...

【BUG】已解决:NOAUTH Authentication required

已解决&#xff1a;NOAUTH Authentication required 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社区主理人…...

全国产服务器主板:搭载飞腾FT2000+/64处理器的高性能加固服务器

近期很多朋友咨询全国产化的服务器主板。搭载的是飞腾FT-2000/64的全国产化服务器主板。他的主要特点是&#xff1a;①丰富的PCIe、千兆以太网、SATA接口&#xff0c;可用作数据处理、存储、通信服务器&#xff1b;②​​​​​​​板载独立显示芯片&#xff0c;对外HDMI/VGA/L…...

OPC UA边缘计算耦合器BL205工业通信的最佳解决方案

OPC UA耦合器BL205是钡铼技术基于下一代工业互联网技术推出的分布式、可插拔、结构紧凑、可编程的IO系统&#xff0c;可直接接入SCADA、MES、MOM、ERP等IT系统&#xff0c;无缝链接OT与IT层&#xff0c;是工业互联网、工业4.0、智能制造、数字化转型解决方案中IO系统最佳方案。…...

【已解决】Django连接MySQL启动报错Did you install mysqlclient?

在终端执行python manage.py makemigrations报错问题汇总 错误1&#xff1a;已安装mysqlclient&#xff0c;提示Did you install mysqlclient? 当你看到这样的错误信息&#xff0c;表明Django尝试加载MySQLdb模块但未找到&#xff0c;因为MySQLdb已被mysqlclient替代。 【解…...

ubuntu gcc g++版本切换

要将 GCC 和 G 的版本从 12.4 降低到 9&#xff0c;你可以按照以下步骤操作&#xff1a; 安装 GCC 和 G 9&#xff1a; sudo apt update sudo apt install gcc-9 g-9 使用 update-alternatives 设置优先级&#xff1a; sudo update-alternatives --install /usr/bin/gcc gcc…...

如何发一篇顶会论文? 涉及3D高斯,slam,自动驾驶,三维点云等等

SLAM&3DGS 1&#xff09;SLAM/3DGS/三维点云/医疗图像/扩散模型/结构光/Transformer/CNN/Mamba/位姿估计 顶会论文指导 2&#xff09;基于环境信息的定位&#xff0c;重建与场景理解 3&#xff09;轻量级高保真Gaussian Splatting 4&#xff09;基于大模型与GS的 6D pose e…...

Java面试八股之什么是Redis的缓存更新

什么是Redis的缓存更新 Redis的缓存更新是指当缓存中的数据发生变化时&#xff0c;需要将这些变化同步到缓存中以保持数据的一致性。缓存更新的目的是确保缓存中的数据始终是最新的&#xff0c;以便用户可以获取到最新的数据。 常见的缓存更新策略包括&#xff1a; 直接覆盖…...

新华三H3CNE网络工程师认证—VLAN使用场景与原理

通过华三的技术原理与VLAN配置来学习&#xff0c;首先介绍VLAN&#xff0c;然后介绍VLAN的基本原理&#xff0c;最后介绍VLAN的基本配置。 一、传统以太网问题 在传统网络中&#xff0c;交换机的数量足够多就会出现问题&#xff0c;广播域变得很大&#xff0c;分割广播域需要…...

Linux-开机自动挂载(文件系统、交换空间)

准备磁盘 添加三块磁盘&#xff08;两块SATA&#xff0c;一块NVMe&#xff09; 查看设备&#xff1a; [rootlocalhost jian]# ll /dev/sd* [rootlocalhost jian]# ll /dev/nvme0n2 扩&#xff1a;查看当前主机上的所有块设备&#xff0c;通过如下指令实现&#xff1a; [root…...

[003-02-10].第10节:Docker环境下搭建Redis主从复制架构

我的博客大纲 我的后端学习大纲 我的Redis学习大纲 1.cluster&#xff08;集群&#xff09;模式-docker版 哈希槽分区进行亿级数据存储 1.1.面试题&#xff1a;1~2亿条数据需要缓存&#xff0c;请问如何设计这个存储案例 1.回答&#xff1a;单机单台100%不可能&#xff0c;肯…...

uni-app学习HBuilderX学习-微信开发者工具配置

HBuilderX官网&#xff1a;简介 - HBuilderX 文档 (dcloud.net.cn)https://hx.dcloud.net.cn/ uni-app官网&#xff1a; uni-app官网 (dcloud.net.cn)https://uniapp.dcloud.net.cn/quickstart-hx.htmlHBuilder下载安装&#xff1a;打开官网 uni-app项目的微信开发者工具配置…...

持续集成08--Jenkins邮箱发送构建信息及测试报告

前言 在持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;的自动化流程中&#xff0c;及时通知团队成员关于构建的成功或失败是至关重要的。Jenkins&#xff0c;作为强大的CI/CD工具&#xff0c;提供了多种通知机制&#xff0c;其中邮件通知是最常用且有…...

专题四:设计模式总览

前面三篇我们通过从一些零散的例子&#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧&#xff0c;从现在开始正式进入设计模式介绍&#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结&#xff0c;和描述具体意义。 设计模式体…...

基于X86+FPGA+AI数字化医疗设备:全自动尿沉渣检测仪

助力数字医疗发展&#xff0c;信迈可提供全自动尿沉渣检测仪专用计算机 随着信息技术的不断进步&#xff0c;医疗也进入了一个全新的数字化时代。首先是医疗设备的数字化&#xff0c;大大丰富了医疗信息的内涵和容量&#xff0c;具有广阔的市场发展前景。 数字化医疗设备&…...

vue2导入elementui组件库

第一步安装 npm i element-ui -S 第二步在main.js中导入 第三步使用然后在运行项目...

Django定时任务框架django-apscheduler的使用

1.安装库 pip install django-apscheduler 2.添加 install_app django_apscheduler 3.在app下添加一个task.py文件&#xff0c;用来实现具体的定时任务 task.pydef my_scheduled_job():print("这个任务每3秒执行一次", time.time()) 4.在app下创建一个manag…...

Ubuntu16.04下MINIGUI 3.2.0环境搭建避坑指南:从依赖安装到HelloWorld运行

Ubuntu 16.04下MINIGUI 3.2.0环境搭建全流程与深度优化指南 为什么选择MINIGUI与Ubuntu 16.04的组合 MINIGUI作为国内自主研发的轻量级GUI系统&#xff0c;在嵌入式领域已有二十余年的技术沉淀。3.2.0版本在保持轻量级特性的同时&#xff0c;增强了对现代嵌入式设备的支持。而U…...

老设备焕新:OCLP更新系统全解析

老设备焕新&#xff1a;OCLP更新系统全解析 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 随着苹果对旧款Mac设备的系统支持逐渐终止&#xff0c;许多仍能正常工作的老设…...

阅读书源校验工具verifyBookSource v2.0避坑指南:如何避免无效书源和重复书源

verifyBookSource v2.0 高效书源管理实战&#xff1a;从校验到优化的完整指南 在数字阅读日益普及的今天&#xff0c;一个优质的书源库能显著提升阅读体验。然而&#xff0c;面对海量书源&#xff0c;如何快速筛选有效内容、剔除重复资源&#xff0c;成为许多阅读爱好者的痛点。…...

告别Redis?在CentOS 7上快速体验国产TongRDS 2.2.x(附与SpringBoot整合对比)

国产内存数据库TongRDS技术评估与SpringBoot整合实战 在技术架构选型的关键时刻&#xff0c;国产基础软件的成熟度与性能表现成为越来越多企业关注的焦点。作为Redis的潜在替代方案&#xff0c;TongRDS凭借其纯Java架构和与Redis协议的高度兼容性&#xff0c;正在技术社区引发热…...

音乐解密技术探秘:从加密困境到跨平台解决方案

音乐解密技术探秘&#xff1a;从加密困境到跨平台解决方案 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gitc…...

如何用kill-doc解决30+文档平台下载难题:免费高效的文档获取方案

如何用kill-doc解决30文档平台下载难题&#xff1a;免费高效的文档获取方案 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档&#xff0c;但是相关网站浏览体验不好各种广告&#xff0c;各种登录验证&#xff0c;需要很多步骤才能下载文档&#xff0c;该脚本…...

语音合成延迟优化:IndexTTS-2-LLM网络IO调优实战

语音合成延迟优化&#xff1a;IndexTTS-2-LLM网络IO调优实战 1. 为什么语音合成总在“等”&#xff1f;从用户卡顿说起 你有没有试过在语音合成页面点下“开始合成”&#xff0c;然后盯着进度条数秒——明明只是一句话&#xff0c;却要等3秒、5秒&#xff0c;甚至更久&#x…...

ccmusic-database新手教程:Gradio输出组件定制——增强Top5结果可读性技巧

ccmusic-database新手教程&#xff1a;Gradio输出组件定制——增强Top5结果可读性技巧 1. 项目简介与背景 ccmusic-database是一个基于深度学习的音乐流派分类系统&#xff0c;它能够自动识别音频文件所属的音乐流派。这个系统在计算机视觉预训练模型VGG19_BN的基础上进行微调…...

进阶篇第5节:共享内存(三)——实战:优化矩阵乘法(Tiling技术)

第二篇进阶篇第5节:共享内存(三)——实战:优化矩阵乘法(Tiling技术) 从朴素到分块,从分块到极致——矩阵乘法的优化之路,就是CUDA性能优化的缩影 写在前面 矩阵乘法是CUDA优化中最经典的案例,没有之一。在筑基篇,我们实现了朴素版本和基础分块版本,性能从 252 GFLO…...

OpenClaw进阶:利用GLM-4.7-Flash实现复杂任务链式执行

OpenClaw进阶&#xff1a;利用GLM-4.7-Flash实现复杂任务链式执行 1. 为什么需要链式任务执行 上周我在整理项目文档时&#xff0c;遇到了一个典型的多步骤任务&#xff1a;需要从十几个Markdown文件中提取关键数据&#xff0c;整理成Excel表格&#xff0c;然后根据内容生成分…...