Instruments 之 使用 Time Profiler 优化启动速度

在性能优化过程中,启动速度优化一直是一个比较大的点。Apple 官方期望 APP 的启动时间为 0.4 s,用户的期待时间为 2 s (来自调查)。不过作为开发者,当然希望我们的 APP 的启动速度能够尽可能的快。若是对 Time Profiler 不熟悉的同学可以先阅读一下先前的文章 Instruments 之 Time Profiler 使用

冷启动和热启动

APP 启动分为冷启动(Cold Launches),当 APP 长时间没有被启动的时候,用户再次启动 APP 的时候就是冷启动,若是手机重启之后,APP 的第一次启动也是冷启动;冷启动对应的是热启动(Warm Launches),当 APP 启动时需要的 dylibs 仍然停留在设备的磁盘缓存的时候,这个时候就是热启动,热启动的速度会更快。

优化案例

使用 Xcode 版本为 8.3.2 ,设备为 iPhone 6 ,系统版本 10.3.1。 APP 每次启动之前需要重启一下手机,达到冷启动的效果。案例使用 raywenderlich 的
Catstagram 启动优化。该案例是一个带图片的列表。

Catstagram

优化 before main()

before main()

APP 启动优化可以分为 2 个部分,一个部分在 main() 函数之前,另一部分在 main()函数之后。对于 APP 的启动细节可以参考 WWDC 的 Optimizing App Startup Time 章节,本文主要讲使用 Time Profiler 来分析 APP ,然后根据分析结果来优化 APP,着重讲解 Time Profiler 的使用过程。
接下来,打开 Catstagram 案例,添加 Scheme 的 DYLD_PRINT_STATISTICS 参数,并设置值为 YES,见下图所示。该DYLD_PRINT_STATISTICS参数用于让 Xcode 控制台输出 APP 在 before main() 时机之前的花费时间。

Scheme
DYLD_PRINT_STATISTICS

设置好了之后,Command + R 在冷启动情况下启动 APP ,可以看到控制台的输出

Total pre-main time: 1.5 seconds (100.0%)
         dylib loading time: 814.09 milliseconds (52.6%)
        rebase/binding time:  52.20 milliseconds (3.3%)
            ObjC setup time: 241.27 milliseconds (15.6%)
           initializer time: 437.29 milliseconds (28.3%)
           slowest intializers :
             libSystem.B.dylib :  19.26 milliseconds (1.2%)
               AsyncDisplayKit : 145.63 milliseconds (9.4%)
                    Catstagram : 277.81 milliseconds (17.9%)

重点关注 Total pre-main time: 1.5 seconds (100.0%) 的信息,冷启动情况在 pre-main 时机中可以看到信息 dylib loading time: 814.09 milliseconds (52.6%) ,也就是说我们的 dylib loading time 加载时间占据了 52.6% 。联想到我们的第三方库是采用 pod 管理,并且是 use_frameworks ,frameworks 是一个可优化点,

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'Catstagram' do
  use_frameworks!
  pod 'AFNetworking'
  pod 'AsyncDisplayKit', '~> 2.2'
  pod 'Yoga', '~> 1.3'
  pod 'Firebase', '~> 3.15'
  #pod 'FirebaseUI', '~> 3.1'
end
frameworks

这个 frameworks 是一个可优化点,打开 Podfile,并注释掉 use_frameworks ,然后命令行执行 pod install 命令 ,更新工程,可以看到工程设置发生了变化。

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'Catstagram' do
  #use_frameworks!
  pod 'AFNetworking'
  pod 'AsyncDisplayKit', '~> 2.2'
  pod 'Yoga', '~> 1.3'
  pod 'Firebase', '~> 3.15'
  #pod 'FirebaseUI', '~> 3.1'
end
非 frameworks

修改好了之后,Command + R 在冷启动情况下启动 APP ,查看控制台的输出。

Total pre-main time: 1.1 seconds (100.0%)
         dylib loading time: 470.55 milliseconds (39.6%)
        rebase/binding time:  31.07 milliseconds (2.6%)
            ObjC setup time: 255.35 milliseconds (21.4%)
           initializer time: 430.58 milliseconds (36.2%)
           slowest intializers :
             libSystem.B.dylib :  12.89 milliseconds (1.0%)
                    Catstagram : 792.04 milliseconds (66.6%)

从 log 中可以看到明显的变化,Total pre-main time 由之前 1.5 seconds 降到 1.1 seconds 。dylib loading time 由之前的 814.09 milliseconds (52.6%) 降到 470.55 milliseconds (39.6%) 。优化效果非常明显。

优化 after main()

after main()

优化完 before main() 之后,开始来优化 after main()。从图中可以看出启动优化的点是集中在 UIApplicationMain()上。
打开 Instruments 选择 Time Profiler 来分析 APP。

Time Profiler
launch 周期

选择 APP 生命周期中的 Launching 生命周期来分析,如上图所示,可以清晰的看到耗时操作主要发生在 log 操作中,所以我们回到关于 log 的这段代码代码中,它可能是一个可以优化的点。

    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        let appearance = UINavigationBar.appearance()
        appearance.backgroundColor = .white
        appearance.barTintColor = .white

        CoolLogger.reportLogs()
        
        return true
    }

上述打 log 代码在 main 线程中执行,所以这段代码是可以优化的,我们将这段代码放到非 main 线程中执行。

      DispatchQueue.global(qos: .background).async {
            CoolLogger.reportLogs()
        }

修改代码之后,重新启动手机,让 APP 进行冷启动,继续使用 Time Profiler 分析 APP,从下图的分析结果总可以看到优化取得了效果,APP 的 Laucning 生命周期没有出现 APP 的生命周期中,说明使用了及其短的时间来完成启动,这时间长度可以忽略。

极速启动

总结

Time Profiler 可以看到代码的运行时长,配合它的Lift Cycle 工具可以用来优化 APP 的启动速度。 Time Profiler 只是一个工具,它只能帮助记录 APP 的运行状态,而开发者可以根据记录的状态分析 APP 的耗时操作,然后进行修改,再用 Time Profiler 验证。

参考

本文是 raywenderlich 的课程笔记,内容参考 Practical Instruments 课程
1、Demo 项目 https://files.betamax.raywenderlich.com/attachments/videos/786/0965b118-95eb-492f-804c-3135c7347130.zip

2、https://videos.raywenderlich.com/courses/74-practical-instruments/lessons/4

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容

  • 当 APP 开发到了一定的阶段,性能优化这个话题就会被提起,性能优化的途径有很多,不过通常都会使用到 Apple ...
    要上班的斌哥阅读 6,912评论 0 21
  • 学习如何使用【Xcode Instruments】来进行错误排查和优化代码。 更新提示:这篇教程由James Fr...
    汝阴龙阅读 1,105评论 0 1
  • 首先如果遇到应用卡顿或者因为内存占用过多时一般使用Instruments里的来进行检测。但对于复杂情况可能就需要用...
    攻克乃还_阅读 1,642评论 0 7
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,471评论 25 707
  • 爱情是棵山楂树 春天小苗靠你助 嫩枝嫩芽勤付出 还要提防虫儿蛀 爱情是棵山楂树 枝繁叶茂更辛苦 虽有明月树间照 也...
    玉露情歌阅读 370评论 0 4