目录
main函数之前
一、冷启动与热启动
我们一般认为杀掉程序,再次启动程序就是冷启动。程序在后台时再回到前台就是热启动。
但实际上杀掉进程后再启动进程并不是真正的冷启动,因为程序已经加载到内存中,我们杀掉程序并不能清除内存中已加载的部分。
杀掉进程,启动5-6个其它进程,覆盖之前的内存,再次启动该进程才能保证是百分百的冷启动。
二、配置环境变量
配置了该环境变量后程序在启动时就会打印启动时间
Total pre-main time: 1.0 seconds (100.0%) |
dylib loading time | 179.81 milliseconds (17.8%) | 动态库加载时间 |
rebase/binding time | 197.74 milliseconds (19.6%) | 内部指针修正(ASLR)/外部指针绑定符号绑定(符号绑定) |
ObjC setup time | 255.18 milliseconds (25.3%) | 类注册时间 |
initializer time | 373.84 milliseconds (37.1%) | load方法耗时,并不是initializer方法 |
slowest intializers | ||
libSystem.B.dylib | 10.84 milliseconds (1.0%) | 系统库 |
libglInterpose.dylib | 69.62 milliseconds (6.9%) | 调试相关 |
mars | 43.44 milliseconds (4.3%) | 系统库 |
158.86 milliseconds (15.7%) | 主程序mach-0 |
三、如何优化
优化 |
dylib loading time | 减少动态库的数量不要超过6个 |
rebase/binding time | 减少项目中的类,有统计去掉2万个类可减少800毫秒所以优化空间较小。但项目中弃用的类要尽量清除 |
ObjC setup time | 减少项目中的类,有统计去掉2万个类可减少800毫秒所以优化空间较小。但项目中弃用的类要尽量清除 |
initializer time | 代码尽量不要在load方法,放在initializer方法,但要注意多次调用问题 |
main函数之后
1、懒加载
2、发挥CPU的价值,多线程初始化
3、xib storyboard 会先转为代码然后执行,效率低。navigationControlelr tabBarController 尽量不要用xid或storyboard
4、在业务逻辑上进行优化
虚拟内存
每个进程都认为自己可以拥有整个内存的使用空间,起始地址是0x00。
虚拟内存 —》地址翻译(映射表、mmu)—》物理内存
操作系统是如何管理不同进程对内存的使用的
虚拟内存的特点
1、安全问题
每个进程都以为自己拥有全部的内存空间,地址从0x0000开始,通过映射表找到对应的物理内存。这样就不可能访问到其它进程的内存空间。
2、使用效率问题
页表大小:Linux 4k iOS 16k
当数据不在内存时,操作系统就会发出中断,将要使用的页表加载进内存,叫缺页异常 PageFault
分页加载使用到哪页数据将页表载入内存,内存不够用时覆盖不活跃的进程(操作系统有自己的算法)
缺页异常会耗费一定的时间,iOS的缺页异常发生,载入页表时还要对页进行签名验证,耗时更长。iOS发生一次缺页时耗时在0.6-0.8s
3、虚拟内存存在的安全问题
每个进程的内存地址固定,存在安全问题。 通过ASLR(随机数)技术进行重定向,可以解决这个问题
4、地址分配
代码的地址分配是根据编译顺序决定的,哪个文件先编译地址就靠前。
行者常至,为者常成!