iOS笔记 - APP性能优化 02:耗电
APP 耗电来源
1 - CPU处理
2 - 网络
3 - 定位
4 - 图像
耗电优化
1 - 尽可能降低 CPU、GPU 功耗
2 - 少用定时器
3 - 优化 I/O 操作
① 尽量不要频繁读写小数据,最好批量一次性读写
② 读写大量重要数时,考虑使用 dispatch_io,其提供了基于 GCD 异步操作文件 I/O 的 API,使用 dispatch_io 系统会优化磁盘
③ 数据量比较大时,建议使用数据库,比如 SQLite、CoreData
4 - 网络优化
① 减少、压缩网络数据
② 如果多次请求的数据是相同,建议使用缓存
③ 使用断点续传
④ 网络不可用时就不要尝试执行网络请求
⑤ 给用户提供一个可以取消长时间运行或速度很慢的网络操作;或者设置一个恰当的超时时间
⑥ 批量传输
比如下载视频流时就不要传输很小的数据包,直接下载整个文件或一大块一大块地下载
再比如下载广告、邮件,可以选择一次性地批量下载然后慢慢展示
5 - 定位优化
① 如果只需要快速定位用户的当前位置,最好使用 CLLocationManager 的 requestLocation 方法,其定位完成后,会自定让定位硬件断电
② 如果不是导航应用,尽量不要实时更新位置
③ 降低定位精度。比如不要使用精度最高的 KCLLocationAccuracyBest
④ 尽量不要使用 startMonitorSignificantLocationChanges,优先考虑使用 startMonitoringForRegion
6 - 硬件检测优化:用户的移动、摇晃、倾斜设备时所产生的动作事件
① 这些事件由加速计、陀螺仪、磁力计等硬件检测,在不需要的场合要及时关闭这些硬件
7 - APP 启动优化:主要针对冷启动。注:通过添加环境变量可以打印出 APP 的启动时间:Edit Scheme-> Run -> Arguments 中添加 DYLD_PRINT_STATISTICS 并置 1(如果想要更详细的日志信息,追加 DETAILS 即可:DYLD_PRINT_STATISTICS_DETAILS)
① dyld 方面
减少动态库、合并一些动态库、定期清理不必要的动态库
减少 objc类、分类的数量,减少 Selector 的使用、定期清理不必要的类和分类
减少 C++ 虚函数数量
Swift 尽量使用结构体
② Runtime 方面
用 initialize 方法和 dispatch_once 取代所有的 __attribute_((constructor))、C++静态构造器、objc 的 +load方法
③ main函数方面
在不影响用户体验的前提下,尽可能将一些操作延迟不要全部放在 finishLaunching方法中
按需加载
APP 的冷启动大致分为三个阶段
1 - dyld(dynamic link editor)APP 的动态链接器,用来装载 Mach-O 文件(可执行文件、动态库等)。启动 APP 时 dyld 要做的事情有
① 装载 APP 的可执行文件,同时会递归加载所有依赖的动态库
② 当可执行文件、动态库都装载完毕之后,会通知 Runtime 进行下一步处理
2 - Runtime。启动 APP 时 Runtime 要做的事情有
① 调用 map_images 进行可执行文件内容的解析和处理
② 在 load_images 中调用 call_load_methods,调用所有 Class 和 Category 的 +load方法
③ 进行各种 objc 结构的初始化,比如注册 objc 类、初始化类对象等
④ 调用 C++ 静态初始化器和 __attribute_((constructor)) 修饰的函数
到此为止,可执行文件和动态库中所有的符号(class、protocol、selector、IMP......)都已经被添加进内存当中,被 Runtime 所管理
3 - 启用 main函数
结论:APP 的启动是由 dyld 主导,并由 Runtime 负责加载成 objc 定义的结构,完成所有初始化操作后,dyld 就会调用 main函数