要优化iOS App的性能,就得先搞清楚屏幕的成像原理.在屏幕的成像过程中,CPU 和 GPU起着至关重要的作用.
一:屏幕成像原理:
CPU (Central Processing Unit):中央处理器
对象的创建和销毁,对象属性的调整,布局计算,文本的计算和排版,图片的格式转换和解码,图像的绘制 (Core Graphics).
GPU (Graphics Processing Unit)图形处理器
纹理的渲染.
手机要把内容要想显示到屏幕上,是需要CPU和GPU相互协作才能完成的:
CPU主要负责计算,比如说界面的布局排版,文字的大小和颜色,图片显示的解码等操作都需要CPU计算,CPU将计算好的数据提交给GPU,GPU就将CPU计算好的数据进行渲染.因为屏幕显示的数据是特定格式的,只有通过GPU渲染过的数据才能显示在屏幕上;GPU把渲染过的数据放到帧缓存区,视频控制器从帧缓存区读取数据显示到屏幕上.
CPU 和 GPU 相互协作
iOS是双缓存机制,有前帧缓存和后帧缓存.渲染效率比较高.
在显示一帧数据(一屏幕数据)之前,首先会发出,一旦发出就意味着要显示一帧的数据了;接下来再发送,发出就意味着一行一行的显示数据,直到填充整个屏幕为止.如果一帧的数据显示完毕,会再次发送开始下一帧数据的显示,如果把每一帧的数据连起来看起来就和动画一样了.
屏幕成像原理
二:卡顿产生的原因
有时候我们拖拽屏幕会发现屏幕不是很流畅,并且会有卡顿现象.那么产生卡顿的原因是什么呢?
CPU计算数据和GPU渲染数据都是需要消耗时间的,如果发出的时候,CPU和GPU还没有把数据处理好,就会把CPU和GPU上一次处理好的数据显示在屏幕上.而CPU和GPU当前正在计算和渲染的数据就丢失了,俗称.也就是说屏幕上显示的还是上一帧( 上一页 )的数据,所以就造成了卡顿.而刚才CPU和GPU没有处理好的数据只有等到下一次的到来才能显示.如图所示:
卡顿产生的原因
知道了屏幕卡顿的原因,就有了解决卡顿的思路:
要保证屏幕不卡顿,就要保证1s刷新60帧,每隔16ms(毫秒)就会又一次信号.也就是我们要在16毫秒内完成CPU的计算和GPU的渲染工作,这样就不会掉帧
三:卡顿优化
尽量使用轻量级的对象,比如用不到事件处理的地方,可以考虑使用代替.
不要频繁的调整的相关属性,比如:等,尽量减少不必要的修改.因为每次调整都要重新计算渲染,消耗的性能就比较多.
尽量提前计算好布局,在有需要时一次性调整对应的属性,不要多次修改.
会比直接设置消耗更多的CPU资源.
图片的最好跟的保持一致.如果图片过大CPU会进行伸缩处理,消耗资源.
控制线程的最大并发数.
尽量把耗时的操作放到子线程.
文本处理(尺寸计算,绘制)
图片处理(解码,绘制):通过方法加载的图片并不能直接显示在屏幕上,这样加载的仅仅是经过压缩的图片的二进制数据,如果想要把图片渲染到屏幕上还要对图片进行解码,解码成屏幕需要的格式.所以如果图片比较多比较大的话,可以提前放到子线程进行解码.最后再放到主线程显示,这样主线程就不会有这些解码的工作就不会造成卡顿.
四:卡顿检测
到现在我们知道,主要是因为在主线程执行了比较耗时的操作造成的.我们可以添加到主线程的中,通过监听状态切换的耗时,以达到监控卡顿的目的.
五:耗电优化
耗电操作主要包含4个方面:
CPU处理,
网络,Networking
定位,Location
图像,Graphics
优化思路:
尽可能降低CPU,GPU功耗.
少用定时器.
优化I/O操作:
尽量不要频繁写入小数据,最好批量一次性写入.
读写大量重要数据时,考虑,其提供了基于GCD的异步操作文件I/O的API.用系统会优化磁盘访问.
数据比较大的,建议采用数据库(比如)
网络优化:
减少,压缩网络数据.比如之前和服务器交互是采用,提交比较大.后来采用,现在有的公司已经使用.
如果多次请求的结果是相同的,尽量使用缓存.
使用断点续传,否则网络不稳定时可能多次传输相同的内容.
网络不可用时不要尝试执行网络请求.
让用户可以取消长时间运行或者速度很慢的操作,设置合适的超时时间.
批量传输(减少发送网络请求的数量).比如:下载视频流时,不要传输很小的数据包,直接下载整个文件或者一大块一大块的下载.如果下载广告,一次性多下载一些,然后慢慢展示.如果下载电子邮件,一次下载多封,不要一封一封的下载.
定位优化:
如果只是需要快速确定用户位置,最好用的方法.定位完成后会自动让定位硬件断点.
如果不是导航引用,尽量不要实时更新位置,定位完毕就关掉定位服务.
尽量降低定位精度.比如尽量不要使用精度最高的.
需要后台定位时,尽量设置为.如果用户不太可能移动的时候,系统会自动暂停位置的更新.
尽量不要使用,优先考虑.
硬件检测优化:
用户移动,摇晃,倾斜设备时,会产生动作()事件.这些事件由加速计,陀螺仪,磁力计等硬件检测.在不需要检测的场合,应该及时关闭这些硬件.
六:App启动优化
App的启动可以分为两种:
冷启动():从零开始启动App.
热启动():App已经在内存中,在后台存活着,再次点击图标启动App.
而我们要做的启动优化,主要是对冷启动进行优化.一般来说,冷启动的时间只要在400毫秒以内就没有问题.超过400毫秒就需要优化了.
通过添加环境变量可以打印出App的启动时间分析:
下添加:
设置为1:打印粗略信息.
设置为1:打印详细信息
App的冷启动可以概括为3大阶段:
:加载可执行文件,加载动态库阶段.
:初始化OC结构,比如初始化类,分类等等.
:调用函数.
启动优化分析:
:
我们点击App图标启动一个App,最开始是由的程序去装载App的可执行文件.是的动态链接器,不管是iOS项目还是Mac OS 项目都会用到它.它是用来装载文件的.(可执行文件,动态库等等).
可执行文件包含我们所写的代码,并不包括项目中用到的动态库,可执行文件中只有动态库的依赖信息,出了要加载可执行文件到内存中以外,还要检查文件依赖哪些动态库,然后去加载这些动态库.加载动态库的时候还会检查这个动态库是否还依赖其他动态库,如果依赖就递归查找加载到内存.
等把可执行文件和动态库都加载到内存中后,就会通知进行下一步处理.
:
启动App时,所做的事情:
调用进行可执行文件内容的解析和处理.
在中调用,调用所有和的方法.
进行各种结构的初始化.(注册,初始化类对象等等).
调用动态初始化器 和 修饰的函数.
到此为止,可执行文件和动态库中的所有符号都已经按格式成功加载到内存中,被所管理.整个OC的运行环境就已经搭建好了.
总结:
App的启动由主导,将可执行文件加载到内存,顺便加载所有依赖的动态库.
并有负责加载成定义的结构.
所有初始化工作结束后,就会调用函数.
接下来就是函数,的方法.
启动优化思路:
:
减少动态库,合并动态库(定期清理不必要的动态库).
减少类,分类的数量,减少数量.(定期清理不必要的类,分类).
减少虚函数的数量.一旦有虚函数就会多维护一张虚表.
尽量使用,不要使用类.
:
用方法和取代所有的,,方法.
:
在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部放在方法中.
按需加载.
七:安装包瘦身
安装包主要由可执行文件,资源组成.
针对资源:
才去无损压缩.
去除没有用到的资源.可以用github上的此工具.
可执行文件的瘦身:
编译器优化:
Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default设置为YES
去掉异常支持,Enable C++ Exceptions、Enable Objective-C Exceptions设置为NO, Other C Flags添加-fno-exceptions
利用AppCode检测未使用的代码:菜单栏 -> Code -> Inspect Code
生成LinkMap文件,可以查看可执行文件的具体组成
image.png
可借助第三方工具解析文件.
领取专属 10元无门槛券
私享最新 技术干货