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函数