所在的位置: ios >> ios发展 >> iOSMemory内存详解

iOSMemory内存详解

0.前言

本文以iOSMemory的相关内容作为主题,主要从一般操作系统的内存管理、iOS系统内存、app内存管理等三个层面进行了介绍,主要内容的目录如下:

iOS是基于BSD发展而来,所以先理解一般的桌面操作系统的内存机制是非常有必要的。在此基础之上,本文会进一步在iOS系统层面进行分析,包括iOS整体的内存机制,以及iOS系统运行时的内存占用的情况。最后会将粒度缩小到iOS中的单个app,讲到单个app的内存管理策略。

1.操作系统的内存机制

为了从根本上更好地理解和分析iOS系统上的内存特性,我们首先需要正确理解一般操作系统通用的内存机制。

冯·诺依曼结构

冯·诺依曼结构(VonNeumannarchitecture)在年就已经被提出了,这个概念当时十分新颖,它第一次将存储器和运算器分离,导致了以存储器为核心的现代计算机的诞生。

在冯·诺依曼结构中,存储器有着重要地位,它存放着程序的指令以及数据,在程序运行时,根据需要提供给CPU使用。可以想象,一个理想的存储器,应该是兼顾读写速度快、容量大、价格便宜等特点的,但是鱼和熊掌不可兼得,读写速度越快的存储器也更贵、容量更小。

但冯·诺依曼结构存在一个难以克服的问题,被称为冯·诺依曼瓶颈——在目前的科技水平之下,CPU与存储器之间的读写速率远远小于CPU的工作效率。简单来说就是CPU太快了,存储器读写速度不够快,造成了CPU性能的浪费。

既然现在我们没办法获得完美的存储器,那我们如何尽量突破冯·诺依曼结构的瓶颈呢?现行的解决方式就是采用多级存储,来平衡存储器的读写速率、容量、价格。

存储器的层次结构

存储器主要分为两类:易失性存储器速度更快,断电之后数据会丢失;非易失性存储器容量更大、价格更低,断电也不会丢失数据。随机访问存储器RAM也分为两类,其中SRAM速度更快,所以用作高速缓存,DRAM用作主存。只读存储器ROM实际上只有最开始的时候是只读的,后来随着发展也能够进行读写了,只是沿用了之前的名字。

上图就是多层存储器的具体情况,我们平时常说的内存,实际上就是指的L4主存。而L1-L3高速缓存和主存相比,速度更快,并且它们都已经集成在CPU芯片内部了。其中L0寄存器本身就是CPU的组成部分之一,读写速度最快,操作耗费0个时钟周期。

简单来说,存储器的分级实际上就是一种缓存思想。金字塔底部的部分容量大,更便宜,主要是为了发挥其存储属性;而金字塔尖的高速缓存部分读写速度快,负责将高频使用的部分缓存起来,一定程度上优化整体的读写效率。

为什么采用缓存就能够提高效率呢?逻辑上理解起来其实很简单,具体来说就是因为存在局部性原理(Principleoflocality)——被使用过的存储器内容在未来可能会被多次使用,以及它附近的内容也大概率被使用。当我们把这些内容放在高速缓存中,那么就可以在部分情况下节约访问存储器的时间。

CPU寻址方式

那么,CPU是如何访问内存的呢?内存可以被看作一个数组,数组元素是一个字节大小的空间,而数组索引则是所谓的物理地址(PhysicalAddress)。最简单最直接的方式,就是CPU直接通过物理地址去访问对应的内存,这样也被叫做物理寻址。

物理寻址后来也扩展支持了分段机制,通过在CPU中增加段寄存器,将物理地址变成了"段地址":"段内偏移量"的形式,增加了物理寻址的寻址范围。

不过支持了分段机制的物理寻址,仍然有一些问题,最严重的问题之一就是地址空间缺乏保护。简单来说,因为直接暴露的是物理地址,所以进程可以访问到任何物理地址,用户进程想干嘛就干嘛,这是非常危险的。

现代处理器使用的是虚拟寻址的方式,CPU通过访问虚拟地址(VirtualAddress),经过翻译获得物理地址,才能访问内存。这个翻译过程由CPU中的内存管理单元(MemoryManagementUnit,缩写为MMU)完成。

具体流程如上图所示:首先会在TLB(TranslationLookasideBuffer)中进行查询,它表位于CPU内部,查询速度最快;如果没有命中,那么接下来会在页表(PageTable)中进行查询,页表位于物理内存中,所以查询速度较慢;最后如果发现目标页并不在物理内存中,称为缺页,此时会去磁盘中找。当然,如果页表中还找不到,那就是出错了。

翻译过程实际上和前文讲到的存储器分级类似,都体现了缓存思想:TLB的速度最快,但是容量也最小,之后是页表,最慢的是硬盘。

虚拟内存

刚才提到,直接使用物理寻址,会有地址空间缺乏保护的严重问题。那么如何解决呢?实际上在使用了虚拟寻址之后,由于每次都会进行一个翻译过程,所以可以在翻译中增加一些额外的权限判定,对地址空间进行保护。所以,对于每个进程来说,操作系统可以为其提供一个独立的、私有的、连续的地址空间,这就是所谓的虚拟内存。

虚拟内存最大的意义就是保护了进程的地址空间,使得进程之间不能够越权进行互相地干扰。对于每个进程来说,操作系统通过虚拟内存进行"欺骗",进程只能够操作被分配的虚拟内存的部分。与此同时,进程可见的虚拟内存是一个连续的地址空间,这样也方便了程序员对内存进行管理。

对于进程来说,它的可见部分只有分配给它的虚拟内存,而虚拟内存实际上可能映射到物理内存以及硬盘的任何区域。由于硬盘读写速度并不如内存快,所以操作系统会优先使用物理内存空间,但是当物理内存空间不够时,就会将部分内存数据交换到硬盘上去存储,这就是所谓的Swap内存交换机制。有了内存交换机制以后,相比起物理寻址,虚拟内存实际上利用硬盘空间拓展了内存空间。

总结起来,虚拟内存有下面几个意义:保护了每个进程的地址空间、简化了内存管理、利用硬盘空间拓展了内存空间。

内存分页

基于前文的思路,虚拟内存和物理内存建立了映射的关系。为了方便映射和管理,虚拟内存和物理内存都被分割成相同大小的单位,物理内存的最小单位被称为帧(Frame),而虚拟内存的最小单位被称为页(Page)。

注意页和帧大小相同,有着类似函数的映射关系,前文提到的借助TLB、页表进行的翻译过程,实际上和函数的映射非常类似。

内存分页最大的意义在于,支持了物理内存的离散使用。由于存在映射过程,所以虚拟内存对应的物理内存可以任意存放,这样就方便了操作系统对物理内存的管理,也能够可以最大化利用物理内存。同时,也可以采用一些页面调度(Paging)算法,利用翻译过程中也存在的局部性原理,将大概率被使用的帧地址加入到TLB或者页表之中,提高翻译的效率。

2.iOS的内存机制

根据官方文档MemoryUsagePerformanceGuidelines(现在已经不更新了)我们能知道iOS的内存机制有下面几个特点:

使用虚拟内存

iOS和大多数桌面操作系统一样,使用了虚拟内存机制。

内存有限,但单应用可用内存大

对于移动设备来说,受限于客观条件,物理内存容量本身就小,而iPhone的RAM本身也是偏小的,最新的iPhoneXSMax也才有4GB,横向对比小米9可达8GB,华为P30也是8GB。根据ListofiPhones可以查看历代iPhone的内存大小。

但是与其他手机不同的是,iOS系统给每个进程分配的虚拟内存空间非常大。据官方文档的说法,iOS为每个32位的进程都会提供高达4GB的可寻址空间,这已经算非常大的了。

没有内存交换机制

虚拟内存远大于物理内存,那如果物理内存不够用了该怎么办呢?之前我们讲到,其他桌面操作系统(比如OSX)有内存交换机制,在需要时能将物理内存中的一部分内容交换到硬盘上去,利用硬盘空间拓展内存空间,这也是使用虚拟内存带来的优势之一。

然而iOS并不支持内存交换机制,大多数移动设备都不支持内存交换机制。移动设备上的大容量存储器通常是闪存(Flash),它的读写速度远远小于电脑所使用的硬盘,这就导致了在移动设备就算使用内存交换机制,也并不能提升性能。其次,移动设备的容量本身就经常短缺、闪存的读写寿命也是有限的,所以这种情况下还拿闪存来做内存交换,就有点太过奢侈了。

需要注意的是,网上有少数文章说iOS没有虚拟内存机制,实际上应该指的是iOS没有内存交换机制,因为在Windows系统下,虚拟内存有时指的是硬盘提供给内存交换的大小。

内存警告

那么当内存不够用时,iOS的处理是会发出内存警告,告知进程去清理自己的内存。iOS上一个进程就对应一个app。代码中的didReceiveMemoryWarning()方法就是在内存警告发生时被触发,app应该去清理一些不必要的内存,来释放一定的空间。

OOM崩溃

如果app在发生了内存警告,并进行了清理之后,物理内存还是不够用了,那么就会发生OOM崩溃,也就是OutofMemoryCrash。

在stackoverflow上,有人对单个app能够使用的最大内存做了统计:iOSappmaxmemorybudget。以iPhoneXSMax为例,总共的可用内存是MB(比硬件大小小一些,因为系统本身也会消耗一部分内存),而单个app可用内存达到MB,达到了55%。当app使用的内存超过这个临界值,就会发生OOM崩溃。可以看出,单个app的可用物理内存实际上还是很大的,要发生OOM崩溃,绝大多数情况下都是程序本身出了问题。

3.iOS系统内存占用

分析了iOS内存机制的特点之后,我们能够意识到合理控制app使用的内存是非常重要的一件事。那么具体来说,我们需要减少的是哪些部分呢?实际上这就是所谓的iOS内存占用(MemoryFootprint)的部分。

上文讲到内存分页,实际上内存页也有分类,一般来说分为cleanmemory和dirtymemory两种,iOS中也有


转载请注明:http://www.aierlanlan.com/tzrz/740.html