老司机高德纳曾经说过:程序开发人员为提升程序效率在错误的方向和时间点浪费了太多的时间,过早优化是编程领域的万恶之源
1.内存优化
一个应用中内存消耗分成两个部分:一个是栈空间一个是堆空间。
栈空间:每一个线程都会对应一个专用的栈空间,栈空间可以在线程存在期间使用,但是有最大栈空间限制。如果超出这个限制,将会导致栈移除,程序被杀死。
以下几种情况,都是由于栈空间溢出,导致程序被杀死:
- 可以被递归调用的最大方法数目。因为每一个方法都会对应一个栈帧,栈帧会消耗一定字节的内存。(这就是为什么,循环调用一定会崩溃,因为函数栈帧消耗的字节数太多,导致内存溢出)
- 方法中定义的变量个数太多。当然这只是一个理论上可能会导致栈溢出的情况,实际开发中基本不会因为定义过多变量被系统kill掉
- 视图的层级太深。递归的调用layoutSubviews方法跟drawRect方法。
堆空间:每一个进城的所有线程都是会对应同一个堆空间。堆空间是系统分配的。通过类创建的对象相关的所有数据都是放在堆中的。所以重量级model在系统收到didReceiveMemoryWarning的时候进行清空,然后在必要的时候重新赋值对于系统优化是非常必要的。
内存管理的原则
- 你可以拥有你自己创建的对象,比如 new,alloc,copy,mutablecopy
- 你可以使用MRC中的retain 或者是ARC中的_Strong来标示对一个对象的强引用
- 在MRC中当不需要一个对象的时候,需要使用release方法来释放对象的持有关系,ARC中不需要做任何操作
避免循环引用引发的内存泄漏
1.delegate weak修饰
2.__weak 修饰被block捕获的局部变量
3.NSTimer,对象持有定时器,定时器也持有对象。解决方法1.自定义清理时机,可以退出控制器时,也可以点击某一个按钮时。
2.能耗
基本没什么好说的,无关紧要
3.多线程
记住:主线程用来更新UI,自线程用来做读写文件等比较耗时的操作
每个线程大概会消耗1KB的内核内存空间。主线程会占用1MB的栈空间,子线程会占用512KB的栈空间。
多线程的弊端:
- 上下文切换,耗费时间
- 创建耗费时间,一般一条线程创建之后启动大概耗费29毫秒
三种多线程的比较
1.GCD - 抽象程度高
- 两种队列开箱即用:main和global
- 可以创建更多的队列
- 硬性要求少于64个线程
2.NSOperationQueue
- 无默认队列
- 应用管理自己创建的队列
- 队列是优先级的队列
- 操作可以有不同的优先级
- 使用cancel可以取消操作
- 可以等待某个操作执行完成
属性默认实用的是atomic,但是这样做属性也不一定是线程安全的。如果需要做线程安全操作,更好的是用锁。所以不要将属性设置为atomic。
注意:@synchronized指令会拖慢应用的运行速度,因为在任何时间内都只有一个线程在临界区。
以下是三种比较常用的锁
1.NSLock
这是一种低级别的锁,一旦获得了锁,那么将会执行临界区中的内容,并且不会超过一个线程执行。释放锁则标志着临界区结束。有个注意点就是 释放锁的操作一定要跟加锁操作在同一线程。
2.NSRecursiveLock
在调用lock之前,NSLock必须先调用unlock。但是正如名字暗示的那样,NSRecursiveLock允许在被解锁之前锁定多次。只要解锁的次数跟锁定的次数相匹配,那么锁就可以释放。
上图是各种锁的性能。附上老司机的关于iOS中锁问题研究文章链接:https://bestswifter.com/ios-lock/
4.应用的首次启动时间
应用首次启动往往会做很多事情,包括
1.加载默认项
2.检查测试版本
3.初始化应用标识符
4.初始化崩溃报告
5.建立分析方法
6.建立UI基础框架
7.建立内存缓存
附上 今日头条开机启动优化的文章:http://www.cocoachina.com/ios/20170208/18651.html
5.UI层面的优化
记住下面几个原则
- 尽量减少主线程中的工作
- 避免视图层级中的多层嵌套
- 尽可能的延迟视图的加载,也就是常说的懒加载。并且对于可以重用的视图,进行复用 https://github.com/facebookarchive/AsyncDisplayKit
- UIImageView 注意分场景下使用imageNamed跟imageWithContentsofFile。使用图片与imageView大家接近,避免imageview对图片缩放操作。
- UITableView的优化:http://www.jianshu.com/p/4780b10dae55
- 慎用自动布局。自动布局在视图比较多的时候非常耗费CPU性能。如果页面元素太多,建议使用原生的frame布局,对于提升帧率有非常大的帮助。当然了marsory对于计算布局有非常大的帮助,往往很复杂的约束,frame要写一大堆代码,但是marsory就可以写几行就可以了。根据业务不同,可以自己做选择。