美文网首页
简单的App启动速度优化

简单的App启动速度优化

作者: GarrettGao | 来源:发表于2021-01-13 10:32 被阅读0次

    分析工具:
    xCode自带工具 Instrument 的 Timer Profiler。

    测试设备:

    1. iPhone6 iOS 12.4.8,这台设备相对来说比较老旧,我们App在次设备上启动速度非常慢,所以效果较明显。
    2. iphone7 iOS 13.4
    3. iPhone11 iOS 14.0.1

    测试方式,从点击录制开始启动App,到App启动页面结束点击停止,观察主线程的耗时。

    测试启动结果

    iPhone6 iOS 12.4.8测试结果:
    20210105145004.jpg

    可以看到主线程的耗时一共是6.04秒,start占用5.71s,_dyld_start占用327ms(这里需要注意,也因为不是第一次启动,所以dyld二次加载存在直接从缓存中加载,所以耗时比第一次启动会短一些)。

    iphone7 iOS 13.4 测试结果:
    image.png

    主线程的耗时一共是1.57秒,start占用1.50s,_dyld_start占用70ms

    iPhone11 iOS 14.0.1 测试结果:
    image.png

    主线程的耗时一共是754ms,start占用642ms,_dyld_start占用111ms

    我们看到最长的时间是iphone6的iOS12系统,6秒的启动时间是我们绝对接受不了的,下面我们看一下在main函数中都是有那些方法调研占用了大多数的时间。

    首先我们选择左下脚的 Call Tree 按钮,选择隐藏系统方法,方便我们查看我们自己的方法。

    20210105145557.jpg

    隐藏系统方能后,只剩下我们代码的方法列表和耗时,但是发现这些方法都是地址,并不是实际解析之后的方法名,如图:


    image.png

    这里需要注意一下需要DSYM解析成对应的方法名,需要修改一下项目buildSetting的设置,在对应的编译模式下,选择 DWARF with DYSM File

    image.png

    如果启动过程中有组件的方法,组件通过cocoapod集成的,需要在对应的组件也设置上,可以通过遍历全局设置:

        post_install do |installer|
      installer.pod_target_subprojects.flat_map { |p| p.targets }.each do |t|
        t.build_configurations.each do |config|
            # 设置debug模式,其他模式类似
            config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf-with-dsym'
    
        end
      end
    end
    

    设置后需要执行一下 pod install,重新把项目run到手机,通过 Time Profiler查看代码耗时:

    image.png

    可以看到,在启动过程中 有三个计较耗时的方法,启动 HBHRouterManager.regisgerRootVC(vc:)方法耗时达到5.71秒,我们项目这个方法是路由注册处理,调用了全局的类列表并组成对应的Scheme链接映射表,所以比较耗时。所以我们要根据实际情况优化我们耗时的方法,或者调优,或者延后调用,不要堵塞主线程的启动过程。尤其是在 Appdelegateapplication(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool方法中 在return之前,千万不要做特别耗时的工作堵塞主线程。可以尝试在此方法 return之前 sleep(10),那么你的App启动肯定在10秒以上。

    我们采用简单方式先处理一下这个耗时的方法:

        // 子线程异步执行注册路由方法,不要堵塞主线程的启动过程
        DispatchQueue.global().async {
            HBHRouterManager.shared.regisgerRootVC(vc: rootViewController)
        }
    

    重新Run,看一下启动耗时:


    20210105180544.jpg
    image.png

    可以看到mainstart调用时间直接降低到了 436ms,App在iPhone6上启动时间从原来的6秒左右降低到739ms。
    再看一下剩下的两台机器:

    iphone7 iOS 13.4 测试结果:
    image.png

    主线程的耗时一共是339ms秒,start占用256ms,_dyld_start占用72ms

    iPhone11 iOS 14.0.1 测试结果:
    image.png

    主线程的耗时一共是146ms,start占用38ms,_dyld_start占用108ms

    以此类推,其他耗时的方法采用对应的优化方案调优,即可实现最简单的启动速度的优化。

    这里只是简单介绍在主线程启动执行时的耗时方法进行优化,不同的启动场景对App的耗时影响也不太一样,苹果给我们例举了几种启动场景:

    1. 重启手机,首次启动App。
    2. 强制退出App,然后启动。
    3. 打开其他App,然后启动你的App。
    4. 使用一个非常大的App(例如,可以使用许多图形资源或实时摄像机输入的App),然后启动您的应用程序。

    还列举了其他影响启动速度的因素:

    1. App动态库的数量,直接影响到dyld加载的时间。

    2. 静态库初始化时:

      1. C++静态构造函数。
      2. 在类或者分类中的+load方法。
      3. 标有clang属性 __attribute__((constructor)) 的方法 。
      4. 链接到App或Framework任何函数的__DATA__mod_init_func

    关于线上版本App的启动时长统计,苹果也给提供了工具,可以直接查看不通版本的启动耗时:
    Xcode -> Window-> Organizer -> Metrics - > Launch Time

    App启动时间统计
    最后附上官网优化文档:苹果官网启动优化文档

    相关文章

      网友评论

          本文标题:简单的App启动速度优化

          本文链接:https://www.haomeiwen.com/subject/sytwoktx.html