【iOS性能优化】启动速度优化

1,039 阅读3分钟

本文尽量简化内容,主写启动优化答题思路,一些相关知识尽量写其它文章来说明。

优化思路

  • 整理启动流程
  • 监控各阶段耗时
  • 解决各阶段耗时问题

iOS启动流程

概述

分为 premain() 和 main() 两个阶段

premain()

  1. Load dylibs (装载、读取 image)
  2. Rebase、Rebind (链接)
  3. Objc (处理一些OC动态特性,包括但不限于以下几点)
    • oc类注册,
    • 将分类信息添加至相关宿主类
    • selector 唯一性检查
  4. Intializers (各种需要初始化的操作,包括但不限于以下几点)
    • C++编译器生成初始化器来完成那些抽象DATA的初始化。
    • objc 中的非懒加载的类的load方法(父类先于子类、主类先于分类)
    • 所有 dylib 的初始化器
    • 创建 c++ 全局静态变量 (对于 c++ 的内存布局不是很了解,等复盘完iOS相关后再往下研究)

main()

如果项目中已经应用SceneDelegate 那么流程自然会有相应的变化。 以下是一般流程描述:

  • dyld调用main()
  • UIApplicationMain()
  • applicationWillFinishLaunching
  • didFinishLaunchingWithOptions

监控耗时

理论大体是上述所述,想要项目实操,发现问题才是第一步。

时间检测的意义

  • 检测 premain、main()的时间 目的主要是为了调试,修复问题。
  • 线上监控 整体启动时间,目的是为了实时检测,监测每个迭代功能更新对于启动时间的影响。 个人认为,在2021年这个时间点,网上找资料、借鉴前辈们的经验,面向优化点解决问题是不难的。那么就要更多的思考怎么杜绝此类问题的出现,真正的面向工程解决问题。

检测 premain 时间

当前 scheme 环境变凉添加 DYLD_PRINT_STATISTICS sceme.png 输出结果为

企业微信20210706-160439.png

检测 main() 时间

  • 配置工程在debug模式下输出符号表 image.png
  • 选择 instruments 中的 App Launch。 运行大约5秒后会关闭程序并显示详细的启动过程

image.png 可以看到启动流程的各个阶段, 可以框选 didFinishLaunchingWithOptions()阶段,分析业务函数调用链。

image.png

线上监控

线上监控,是启动优化非常重要的一环。没有线上数据的监控,只会一次次重复问题排查的苦力活。 目前了解到的线上监控系统有,Metrics(美团)、字节跳动 目前负责的App和大厂超级App没法比,暂时使用比较简单的嵌入式代码方案。 未完待续

解决方案

根据上文,列举一些可以优化的点

解决方案(premain)

  • Load dylibs : 减少 dylib 数量,可以转为静态库的尽量转换为静态库, 减少bundler 资源数量
  • Rebase/Bind : 减少无用类、无用函数、无用分类.
  • Objc setup :
  • Initializers : 减少 load 方法耗时,减少 c++ 静态全局变量

解决方案(main)

  • 通过 instruments 发现耗时严重方法,选择后台线程进行或者等待首帧页面出现后调用。
  • 二进制重排 未完待续

产品层面

未完待续