N久没维护这个博客了,从开始接触编程到如今已经三四年了。不太习惯写博客,这应该是个很差的习惯。因此从哪哪天开始,我得改变本身 (: .算法
文采不太好,所以不少的文章都会借鉴他人的,可是我必定会注明是转载,毕竟如今产权抓的重啊...
编程
0. 概述框架
内存,简单来讲就是内部存储,复杂来讲要从冯·诺依曼计算机结构提及。冯·诺依曼结构,也称作普林斯顿结构,目前和哈佛结构相对,指出了计算机由运算器、控制器、存储器、输入和输出设备几大部件组成。现在咱们我的用的机器估计都是这个套路,并且运算器和控制器都合在一块儿,就是CPU,中央处理器。那么内存就是CPU能直接读写访问数据的地方(寄存器是在CPU内的,不算哈),有些朋友说谁谁谁的iPhone内存16G、64G,我只能说这个理解方法仅限于存储部件放在手机里(内)了,严格来说这算“外存”,咱们要讨论的不是这个。ide
冯·诺依曼结构还说了,内存是用来存啥的呢?指令+数据!(哈佛的恐怕就不同了)对于咱们开发者来讲,指令基本就是代码逻辑,至于数据么变量常量确定都算是的了。函数
内存有多大?不大,现今主流的我的机器也就几G的样子。iPhone? 通通1G。布局
咱们操做系统都是运行在内存之上的,1G好像不算大,因此为了支持多进程,也为了支持大程序,抽象的虚拟存储的概念诞生了。性能
简要的概念先陈述到这,下面详细说。哦,对了,ARC和MRR我仍是得提一下,这个要是真不知道还真的本身先去了解一下去。优化
1. 通用内存基本原理ui
说iOS的内存,有必要先看看通常的计算机都是怎么干的,iPhone也是计算机,通用的道理同样要遵循。这里提两方面:虚存的概念,内存内容的大体分布。操作系统
虚拟存储系统。刚刚提到了,物理内存就那么大点,可是还要跑多个程序,还要接受消耗很大内存的程序,这怎么办?凉拌。搞计算机的人都是很聪明的,在操做系统层面作了物理地址和逻辑地址之间的映射转换,固然处理器硬件上也作了支持。一个程序在运行时,实际要用到的指令和数据都是颇有限的,不可能从头至尾同时用。那么对于一个程序来讲,伪装本身有很是大的空间,实际上只要有条理的把暂时要用到的部分放进物理内存供CPU访问就好,这样第二个问题解决了。那既然每一个程序(进程)只用一小块,那整个物理内存就能够分给多个程序(进程)用了,第一个问题也迎刃而解。固然,这样作的前提是,数据和指令的动态进出,用完了的暂时不用的踢出内存,须要用的及时加载进来。这个具体的实现方式就多种多样了,不少实现方式是在外存中开了个交换区供换入换出,但iOS可略有不一样。
内存的大体分布。不久之前,我发了一篇文章整理了Mach-O文件的格式分析,里面很复杂地放了好多东西,包括咱们Build打包时的代码和数据。而Mach-O文件正是咱们开发内容的一个静态展示形式,要想在运行的时候看样子,就得看这文件里包含的东西是怎么放进内存的。Objective-C是基于C的,不放看下C程序进程的内存分布:
最简单来讲分为两大部分:指令+数据。再细分一点,五部分:代码(指令),初始化数据区,未初始化数据区,堆,栈。
其实,这个内存中的布局方式大部分操做系统中的大部分进程都是相似的。Objective-C的程序包对运行时有着复杂的支持和内容划分,但也都是在这个大的框架下进行的。
2. iOS的内存管理
其实,iOS的内存管理和其它操做系统大同小异。这里按照苹果文档所述,重点对堆内存分配整理下。
iOS的内存管理分为几个层面,从系统到libmalloc,ARC环境下,编译器也会帮助开发者作“力所能及”的优化处理。
首先,iOS和其它系统同样,操做系统内核会作虚拟存储到物理内存的映射管理,并作内存分页,每页4K。多个页构成一个内存区块统一管理,负责管理的对象是VM object,其中包含了pager、size、resident pages等诸多属性。全部的内存分配最终都将交由系统来处理(好比vm_allocate/mach_vm_allocate)。
而开发中,在系统内核的基础上,iOS使用libmalloc。不论是Objective-C的[NSObject alloc],仍是C代码的对内存分配,重任都会落到malloc库上,释放也是如此,最终都将使用malloc库中的free()。malloc库中有不少malloc的同族函数能够动态分配内存。malloc库中定义了zone的概念,并实现了不一样的zone(如nano zone和scalable zone),并根据内存需求的大小使用不通算法对nano、tiny、small、large量级的内存进行分配和释放管理。默认状况,在第一次调用malloc时,系统会生成一个default zone,后续的默认分配在此进行。好比,malloc_zone_xxx()函数最终都对特定的zone进行分配操做,执行zone->xxx()。每一个zone都以链表的形式对已分配过的内存作cache处理,避免频繁对内核系统发起申请。malloc的内部实现都是开源的,感兴趣的能够去了解去看。
最后强调一下iOS特别须要注意的点:
当前的主流iPhone实际物理内存都不超过1G,能够说不算大。不过和Android机比起来,我不得不为苹果的设计称赞,1G空间利用得如此高效,性能不差,也控制了发热。
那么在这仅有的1G内存中,iOS的操做系统更是抛弃了没必要要的复杂——系统层面不支持App内存页换出。当内存吃紧时,对于能够从新载入的只读数据来讲,直接清理掉,而对于可写的数据,只能经过App本身去管理维护。内存紧张时,iOS会向App发起memory warning,不配合释放足够内存者,杀!
关于Instruments及内存调试,会在后续文章详细整理出来。