美文网首页iOS开发iOS 的那些事儿
iOS启动优化之系统预热(prewarm)

iOS启动优化之系统预热(prewarm)

作者: 果哥爸 | 来源:发表于2022-11-30 21:13 被阅读0次

    一. 背景

    我们从启动统计数据上发现,在iOS15及以上相关系统,经常会出现启动耗时几十秒的情况,通常是load方法的加载就已经达到几十秒了,而且都是相对性能较好的机型。

    image.png image.png

    由于苹果系统存在watchdog机制,针对App启动的启动,watchdog的时间限制是20s,如果启动超过20s,就会被watchdog强制杀死进程,退出应用。

    但这里统计出来启动时长,很明显很大部分已经超过20s了,但是依然正常启动,说明要不就启动统计方法有问题,要不就存在一些异常情况,出现数据异常。

    二. 分析

    针对出现的机型主要是在iOS15及以上系统,因此依据这个线索进行排查。终于找到了关于prewarm的相关资料,具体详见: 【About the app launch sequence】

    1. prewarm 机制

    AppleiOS 15 中引入了prewarm (预热)机制,系统可能会根据设备的情况,比如当设备内存和磁盘空间充足以及用户启动该App的时间习惯等,提前帮你预热(prewarm) 你的 App

    也就是提前启动不再运行的 App 进程,以减少用户手动启动 App 等待的时间。prewarm 执行一个 App 的启动序列直到(但不包括)当 main() 调用 UIApplicationMain。也就是prewarm帮忙提前完成了pre-main之前的所有操作。

    这为系统提供了一个机会来构建和缓存它需要的任何低层结构,以期待一个完整的启动。也就是说,prewarm 机制可以减少启动时间,我们甚至可以在 load 方法中做一些资源的预加载。

    2. 原因

    因为iOS15及以后的系统,苹果添加这种预热的操作:prewarm,系统提前执行了启动的pre-main之前的所有操作,然后暂停,等到用户真正启动的时候,才会继续执行mian之后的相关启动操作,而我们App启动耗时统计是从cocoapods排序的第一个库的load时间开始,然后到首页的viewDidAppear结束。

    因此如果是该App被预热了,也就是库的load等方法先执行,这时候统计起始时间已经标记,然后暂停,暂停这段时间也被算进去,导致启动耗时尤其是load方法的加载出现几十秒这种情况,统计数据出现了偏差,之所以只有统计到几十秒的,而没有几分钟或者几个小时,是因为统计库做了过滤,超过1分钟,就直接丢弃这次统计。

    三. 解决方法

    我们可以根据如下方法判断此次启动是否为预热prewarm启动:

     func isPrewarmLaunch() -> Bool {
            let systemVersion = UIDevice.current.systemVersion.toFloat() ?? 0.0
            if systemVersion >= 15.0 {
                let environment = ProcessInfo.processInfo.environment
                for key in environment.allKeys() {
                    if key.contains(substring: "prewarm") {
                        return true
                    }
                }
            }
            return false
        }
    

    因此决定启动组件里面添加判断,判断此次启动是否为预热prewarm启动,如果此次启动为预热prewarm启动,则统计的起始点用main函数的开始执行的时间作为起点,如果不是预热启动,则依然使用cocoapods排序的第一个库的load的加载时间作为起点。

    不过这里需要对你的App是否接入UIScene做区分判断:

    对于接入 UISceneApp

    • application:didFinishLaunchingWithOptions: 可能会被调用(并不总是发生)

    • scene:willConnectToSession:options: 未被调用。事实上,SceneDelegate 直到 App 打开才创建。

    对于没有接入 UISceneApp

    • application:didFinishLaunchingWithOptions: 不会调用。

    因此,如果 App 接入了 UIScene,又没做特殊处理的话,会因为 prewarm 机制的 bug 而导致 iOS 15 用户日活异常增多。

    因为我们业务线相关的App没有接入UIScene,因此我们这里直接采取上面的优化方案。

    四. 引用

    [About the app launch sequence]

    [iOS BugFix|接入 UIScene 遇到的一些问题及解决方案]

    相关文章

      网友评论

        本文标题:iOS启动优化之系统预热(prewarm)

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