启动优化

330 阅读3分钟

启动优化(一)

两个阶段main(pre-main)之前、main阶段

一、pre-main阶段时间查看,在xcode里面设置环境变量DYLD_PRINT_STATISTICS,打印时间

**Total pre-main time:  20.71 milliseconds (100.0%)**

**dylib loading time:  44.69 milliseconds (215.7%)**

**rebase/binding time: 126687488.8 seconds (147130233.7%)**

**ObjC setup time:  11.13 milliseconds (53.7%)**

**initializer time:  52.46 milliseconds (253.2%)**

**slowest intializers :**

**libSystem.B.dylib :   3.45 milliseconds (16.6%)**

**libBacktraceRecording.dylib :   7.26 milliseconds (35.0%)**

**libobjc.A.dylib :   0.96 milliseconds (4.6%)**

**CoreFoundation :   0.85 milliseconds (4.1%)**

**libMainThreadChecker.dylib :  38.03 milliseconds (183.6%)**
  • 1、dylib链接动态库,苹果官方建议不大于6个,可以合成一个大的库。
  • 2、rebase/binding:地址修正/符号绑定(RSLR:地址空间布局随机化,随机偏移值加载再进程的虚拟空间前)
  • 3、ObjC setup:OC内容注册(2万个类 约= 0.8秒)
  • 4、initializer:load方法加载的时间

优化方案:二进制重排

二、main阶段优化

  • 1、类尽量使用懒加载,即不实现load方法
  • 2、发挥cpu的价值,多线程初始化
  • 3、Xib、Sb会先解析成代码,首个显示的页面别用

三、虚拟内存和物理内存

*某个技术的出现,是为了解决问题,我们通过问题查看本质

1、物理内存我们知道是我们的内存条,那虚拟内存是什么,为什么会有虚拟内存?

*物理内存会存在内存浪费和安全问题

a、计算机早期是没有虚拟内存的,全部都是物理地址,它是将整个进程(应用程序)加载到内存,会造成内存浪费。
b、物理内存是连续的地址,进程加载到内存中是顺序的,所以可以通过地址偏移,拿到其他程序的数据,这样是不安全的。

2、虚拟内存和物理内存关系

虚拟地址 --> 【映射表(页表)】--> 物理内存

进程在运行的时候,会开辟一块虚拟内存,cpu访问数据的时候,通过虚拟地址(寻址),根据系统管理的页表,(CPU的MMU(CPU的一个硬件),即内存管理单元,找到物理地址)转换成物理地址(地址翻译)。这样就无法访问其他进程的数据。(解决安全问题)

3、内存分页管理(内存使用率,效率问题,解决内存浪费问题)

1、以页为单位,而不是字节,如果映射表以字节为单位,那就占用了很大,

终端:PAGESIZE

mac os、linux 一页4kb 4096字节/ ios一页 16kb

1、页面是有分0和1的,0表示无数据,当前数据不在物理内存中。

2、整个应用程序加载的时候,并不会把应用的所有数据放到内存中,只会放用到的部分。

3、如果发现为P2为0,会出现页中断,缺页异常,操作系统会发出的异常,操作系统阻塞当前进程,将磁盘对应的P2的数据加载到物理内存,将虚拟内存指向物理内存。

进程虚拟页表

1P1
0P2
1P3
1P4

4、内存是一页页加载的,所以不够用时,会根据页面置换算法,覆盖不活跃的页面,保证当前进程正常运行,所以内存永远够用。

4、新问题:进程加载到虚拟内存时,都是从0xf0000开始的,(通过地址访问函数)所以是不安全的,代码hook,很容易被静态注入,所以衍生出了ASLR。虚拟内存加载前,加个偏移值。

5、二进制重排,缺页异常,因为代码在mach.o中的位置是根据文件的顺序生成的(编译的顺序),所以加载到虚拟内存中不都是1

ios页中断时

1、数据加载到磁盘,磁盘加载到物理内存,将虚拟内存指向物理内存。

2、加载某一页的时候,还会对某一页做签名验证。