iOS性能优化相关笔记

iOS性能优化相关笔记

  • 卡顿优化CPU

1、尽量使用轻量级的对象,比如用不到事件处理的地方,可以考虑使用CALayer取代UIView
2、不要频繁的调用UIView的相关属性,比如frame、bounds、transform等属性,尽量减少不必要的修改
3、尽量提前计算好布局,在有需要时一次性调整对应的属性,不要多次修改属性
4、Autolayout会比直接设置frame消耗更多的CPU
5、图片的Size最好刚好和UIImageView的size保持一致
6、控制一下线程的最大并发数
7、尽量把耗时操作放子线程(文本处理,图片处理)

卡顿优化GPU
1、尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张图片显示
2、GPU能处理的最大纹理尺寸是4096*4096,一旦超过了这个尺寸,就会占用CPU资源进行处理,所以尽量不要超过这个尺寸
3、尽量减少视图数量和层次
4、减少透明的视图(alpha < 1),不透明的就设置opaque为YES
5、尽量避免出现离屏渲染

在OpenGL中,GPU有2中渲染方式
1、On-screen Rendering:当前屏幕渲染,在当前用于显示的屏幕缓冲区进行渲染操作
2、Off-Screeen Rendering:离屏渲染,在当前屏幕缓冲区外新开辟一个缓冲区进行渲染操作

离屏渲染消耗性能的原因?
1、需要创建新的缓冲区
2、离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕切换到离屏,等到离屏渲染结束后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文环境从离屏切换到当前屏幕

哪些操作会触发离屏渲染?
光栅化,layer.shouldRasterize = YES
遮罩,layer.mask
圆角,同时设置layer.maskToBounds = YES、layer.cornerRadius>0(考虑利用CoreGraphics绘制裁剪圆角,或者让UI提供圆角图片)
阴影,layer.shadowXXX(如果设置了layer.shadowPath就不会产生离屏渲染)

耗电的主要来源
CPU处理、网络、定位、图像

耗电优化
1、尽可能降低CPU、GPU功耗
2、少用定时器
3、优化I/O操作
尽量不要频繁写入小数据,最好批量一次性写入
读写大量重复数据时,考虑用dispatch_io,它提供了基于GCD的异步操作文件I/O的API。用dispatch_io系统会优化磁盘访问
数据量比较大的,建议使用数据库
4、网络优化
减少、压缩网络数据
如果多次请求的结果是相同的,尽量使用缓存
使用断点续传,否则网络不稳定时可能多次传输相同的内容
网络不可用时,不要尝试执行网络请求
让用户可以取消长时间运行或者速度很慢的网络操作,包括设置合适的超时时间
批量传输
5、定位优化
如果只是需要快速确定用户位置,最好用CLLocationManager的requestLocation方法。定位完成后,会自动让定位硬件断电
如果不是导航应用,尽量不要实时更新位置,定位完毕就关掉定位服务
尽量降低定位精度,比如尽量不要使用精度最高的kCLLocationAccuracyBest
需要后台定位时,尽量设置pausesLocationUpdatesAutomatically为YES,如果用户不太可能移动的时候系统会自动暂停位置更新
尽量不要使用startMonitoringSignificantLocationChanges,优先考虑startMonitoringForRegion:
6、硬件检测优化
用户移动、摇晃、倾斜设备时,会产生动作(motion)事件,这些事件由加速度计、陀螺仪、磁力计等硬件检测。在不需要检测的场合,应该及时关闭这些硬件

  • APP启动优化

APP启动可以分为两种:
1、冷启动:从零开始启动
2、热启动:APP已经在内存中,在后台存活着,再次点击图标启动APP

APP的启动优化,主要针对冷启动进行优化
通过添加环境变量可以打印处APP的启动分析(Edit scheme -> Run -> Argument)
DYLD_PRINT_STATISTICS设置为1(dyld_print_statistics)
如果需要更详细的信息,那就将DYLD_PRINT_STATISTICS_DETAILS设置为1

main之前的加载过程
1)dyld 开始将程序二进制文件初始化
2)交由ImageLoader 读取 image,其中包含了我们的类,方法等各种符号(Class、Protocol 、Selector、 IMP)
3)由于runtime 向dyld 绑定了回调,当image加载到内存后,dyld会通知runtime进行处理
4)runtime 接手后调用map_images做解析和处理
5)接下来load_images 中调用call_load_methods方法,遍历所有加载进来的Class,按继承层次依次调用Class的+load和其他Category的+load方法
6)至此 所有的信息都被加载到内存中
7)最后dyld调用真正的main函数

APP的冷启动可以概括为3大阶段
1、dyld
2、runtime
3、main

dyld,Apple的动态连接器,可以用来装载Mach-o文件(可执行文件、动态库)
启动APP时,dyld所做的事情有:
1、装载APP的可执行文件,同时会递归加载所有依赖的动态库
2、当dyld把可执行文件、动态库都装载完毕后,会通知Runtime进行下一步处理

启动APP时,runtime所做的事情有
1、调用map_images进行可执行文件内容的解析处理
2、在load_images中调用call_load_methods,调用所有Class和Category的load方法
3、进行各种objc结构的初始化(注册Objc类、初始化对象等等)
4、调用C++静态初始化器和__attribute__((constructor))修饰的函数
到此为止,可执行文件和动态库中所有的符号(Class,Protocol,Selector,IMP)都已经按格式成功加载到内存中,被runtime所管理

总结:
APP的启动由dyld主导,将可执行文件加载到内存,顺便加载所有依赖的动态库
并由Runtime负责加载成objc定义的结构
所有初始化工作结束后,dyld就会调用main函数
接下来就是UIApplicationMain函数,AppDelegate的application:didFinishLaunchingWithOptions:方法

APP的启动优化
dyld阶段
1、减少动态库、合并一些动态库(定期清理不必要的动态库)
2、减少Objc类、分类的数量,减少Selector数量(定期清理不必要的类个分类)
3、减少C++虚函数数量
4、Swift尽量使用struct

runtime阶段
用+initialize方法和dispatch_once取代所有的__attribute__((constructor))、C++静态构造器、ObjC的+load

main阶段
在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部finishLaunching方法中
按需加载

App启动过程
1、解析Info.plist
2、加载相关信息、权限检查
3、沙箱建立、权限检查

程序执行
1、main函数
2、执行UIApplicationMain函数
创建UIApplication对象
创建UIApplicationDelegate对象并复制
读取配置文件info.plist
创建应用程序的Main RunLoop循环
3、UIApplicationDelegate对象开始处理监听到的事件

安装包瘦身
1、资源(图片、音频)
采用无损压缩
去除没有用到的资源(https://github.com/tinymind/LSUnusedResources)
2、可执行文件瘦身
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
3、利用AppCode检测未使用的代码:菜单栏->Code->Inspect Code
4、编写LLVM插件检测出重复代码、未被调用的代码

LinkMap
生成LinkMap查看每个类占用的大小
https://github.com/huanxsd/LinkMap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值