做一款APP,它的的性能稳定性问题使我们有限要考虑的,首先我们从几个大方向去谈谈这个问题.
1.APP 的启动
启动分为冷启动与热启动:
1.1 冷启动(Cold Launch)就是APP 从零开始.
1.2 热启动(Warm Launch)APP已经在内存中,在后台存活,点击图标再次启动.
我们主要研究冷启动, 冷启动的四大阶段:
1.dyld 加载可执行文件,动态库(递归加载).
1.1 dynamic link editor(动态链接编辑器).
1.2 dynamic loader(动态加载器).
2.runtime.
2.1调用map_images进行可执行文件内容的解析和处理.
2.2在load_images 中调用call_load_method,调用Class和Category的+load方法,进行各种objc结构初始化.
2.3 调用C++ 静态初始化器.
到此为止,可执行文件和动态库中所有的符号
(Class,Protocol,Selector,IMP,...)
都已经按格式成功加载到内存中,被 runtime 所管理
3.main()函数执行后.
main() 函数执行后的阶段,指的是从 main() 函数执行开始,
到 appDelegate 的 didFinishLaunchingWithOptions 方法里首屏渲染相关方法执行完成.
3.1首屏初始化所需的配置文件的读写操作.
3.2首屏列表大数据读取.
3.3首屏渲染大量计算.
4.首屏渲染完成后.
总结:
APP的启动由dyld主导,将可执行文件加载到内存,顺便加载所有依赖的动态库, 并由runtime负责加载成objc定义的结构,所有初始化工作结束后,dyld就会调用main函数, 接下来就是UIApplicationMain函数,AppDelegate的application:didFinishLaunchingWithOptions:方法.
2.安装包瘦身.
3.卡顿问题优化.
4.耗电量优化.
优化方案:
一. 启动阶段优化
1. dyld 阶段:
1).减少动态库的加载,合并一些动态库.
2).减少Objc类、分类的数量,减少Selector(选择器)数量.
3).Swift 尽量使用Struct、枚举.
2. runtime阶段:
用+initialize方法和dispatch_once取代C++ 的静态构造器、Objc的+load.
(因为在+load()方法里,runtime进行方法替换操作会带来4ms的损耗)
3. main()函数执行后
1.main()函数开始执行后到首屏渲染完成前的这一段时间,只处理首屏相关业务,其他的非首屏业务的初始化(监听注册、配置文件读取...)放在首屏渲染完成后再做处理.
4.首屏渲染
1.不使用xib, 直接使用代码加载首屏视图.
2.NSUserDefaults实际上是在Library文件夹下会产生一个plist文件,如果文件太大的话,一次读取到内存中比较耗时,需要拆分.
3.每次用NSLog方式打印会隐式的创建日历(Calendar),需要删减启动业务的NSLog.
4.启动时发送的网络请求,都可以统一在异步线程中请求.
二. 安装包瘦身
安装包(IPA) == 资源 + 可执行文件
1.资源(图片、音频、视频)采取无损压缩,除去无用的资源.
2.编译器优化,去掉异常支持, 利用AppCode, 编写LLVM插件检测重复未被调用代码.
三. 卡顿问题
- 尽可能减少GPU、GPU 的资源消耗.
- 尽量用轻量级的对象.(比如在用不到事件点击的情况使用CALayer 代替UIView)
- 不要频繁的调用UIView 的相关属性.
- 尽量提前计算好布局,尽量减少多次属性的修改.
- Autolayout会直接消耗更多的CPU资源.
- 控制线程的最大并发数.
- 减少视图的层次.
- 减少透明视图的设置.
- 把耗时操作放在子线程.(文本处理(尺寸计算、绘制)、 (图片处理(解码、绘制)))
- 离屏渲染
概念:
在OpenGL中,GPU有2种渲染方式:
On-Screen Rendering:当前屏幕渲染,在当前用于显示的屏幕缓冲区进行渲染操作.
Off-Screen Rendering:离屏渲染,在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作.
离屏渲染消耗性能的原因
需要创建新的缓冲区
离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文环境从离屏切换到当前屏幕.
离屏渲染的触发:
光栅化: layer.shouldRasterize = YES;
遮罩: layer.mask
圆角: 设置layer.masksToBounds = YES、layer.cornerRadius > 0(考虑通过CoreGraphics绘制裁剪圆角,或者叫UI提供圆角图片)
阴影: 设置了layer.shadowPath就不会产生离屏渲染
11.内存泄漏查找:
Analyze
学 名: 静态分析工具- 查 找: 可以通过 Product ->Analyze 菜单项启动- 快捷键: CMD+shift +b.- Analyze主要分析以下四种问题:
- 逻辑错误:访问空指针或未初始化的变量.
- 内存管理错误:如内存泄漏等.
- 声明错误:从未使用过的变量.
- Api调用错误:未包含使用的库和框架.
Instruments
学 名: 动态分析工具- 查 找: Product ->Profile 菜单项启动- 快捷键: CMD + i.
简 介:它有很多跟踪模块可以动态分析和跟踪内存, CPU 和文件系统.
四. 耗电量优化
1.尽可能降低CPU、GPU的功耗.
2.少用定时器.
3.优化 i/O操作.
3.1尽量不要频繁的写入小数据,最好批量一次性写入.
3.2 读大量重要的数据时,考虑用dispatch_io, 其提供了基于GCD的异步操作文件I/O的API, 用dispatch_io系统会优化磁盘访问.
3.3数据量比较大的时候使用数据库(SQLite、FMDB...)
4.网络优化
4.1 减少、压缩网络数据.
4.2 多次的网络请求相同,使用缓存或者数据库.
4.3 断点续传,否则网络不稳定的时候可能多次传入的内容相同.
4.4 网络不可用时,不要尝试网络请求.
4.5 让用户可以取消长时间运行的网络操作,设置合适的超时时间.
4.6 批量传入,不要一次一次请求,使用异步加载.
5.定位优化
5.1 如果只是快速定位用户位置最好使用CLLocationManager的requestLocation方法,定位完成后,会自动让定位硬件断点.
5.2 如果不是导航应用,尽量不要实时更新位置,定位完毕后就关掉定位服务.
5.3 需要后台定位时,尽量设置pausesLocationUpdatesAutomatically 为 YES(如果用户不移动时,系统会自动暂定位置更新).
5.4 尽量不要使用startMonitoringSignificantLocationChange(开始监视重要的位置更改),优先考虑startMonitoringForRegion(开始区域监控)
网友评论