减少卡顿
- 尽量减少视图数量和层次
- 减少透明的视图
- 尽量避免出现离屏渲染
离屏渲染
如果要在显示屏上显示内容,我们至少需要一块与屏幕像素数据量一样大的frame buffer,作为像素数据存储区域,而这也是GPU存储渲染结果的地方。
如果有时因为面临一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。
GPU离屏渲染:采用画家算法,把每一层依次输出到画布,如果父layer剪裁成圆角,容器子layer因为父容器有圆角,也要被剪裁,但这时还在渲染队列中,此时需要在新内存中,把容器以及子layer依次画好,剪裁完成,再放到frame buffer
中。
消耗性能原因
- 需要创建新的缓冲区
- 整个过程需要多次切换上下文环境,从
on-screen
到off-screen
,等渲染结束后,将离屏缓冲区结果显示到屏幕上,再讲上下文从off-screen
切换到on-screen
哪些会触发离屏渲染
- 光栅化
layer.shouldRasterize= YES
。 隐式的创建一个位图,各种阴影遮罩效果保存在位图中缓存,如果对应的layer极其sublayers没有发生改变,在下一帧的时候可以直接复用,减少渲染频率。但是否有助于优化性能取决于缓存的位图是否被有效复用。 - 遮罩
layer.mask
-
圆角 同时设置
layer.maskToBounds = YES
,layer.cornerRadius >0
- 阴影
layer.shadowoffset...
, 但是layer.shadowPath
不会产生离屏渲染
卡顿检测
通过使用监听 runloop的状态切换的耗时达到监控卡顿的目的
APP启动优化
启动分为3大阶段
dyld(dynamic link editor)
动态链接,装在Mach-O文件- 装在APP可执行文件,递归加载所有依赖的动态库
- 都完毕后,通知runtime进行下一步处理
runtime
- 调用
map_images
进行执行文件内容的解析和处理 - 在
load_images
中调用call_load_methods
, 调用所有class和category
的+load
方法 - 进行objc结构初始化,注册类,初始化对象等
- 可执行文件和动态库中所有符号Class,Protocol, Selctor, IMP 都已经加载完成
- 调用Main函数
- 调用
main
UIApplicationMain
和didFinishLaunchingWithOptions
方法
优化方案:
dyld
- 减少动态库,合并动态库
- 减少Objc类,分类的数量
runtime
- 用
+initialize
方法和dispath_once代替+load方法
- 用
main
- 按需加载
更多详细优化方案见iOS 应用启动耗时分析及优化