App启动优化

我们在使用某些超级App时,第一感受就是这款App怎么这么长时间才启动起来,等待的时间过长可能我们自己就把App杀掉了,有的甚至可能没有第二次启动机会就被卸载掉了,这个启动时间是非常影响用户体验的。虽然我现在开发的App还不是超级App,启动时间也说不上很慢,但是毕竟启动时间对于用户来说是越短越好,本着这个目标,我希望这次的优化能够更好的优化App启动时间,给用户带来更好的用户体验。

1、App启动类型

iPhone App的启动可以分为两种类型:冷启动和热启动。

1.1 冷启动

App启动前,其进程已被杀死或根本就没有在系统中存在,这种情况下点击App图标启动,就是一次冷启动过程。

1.2 热启动

App启动后,将App切到后台,但是进程没有别杀死,进程还在系统中存在,这种情况下重新点击App图标进入App,就是一次热启动过程。

针对上述两种启动,我们一般优化是指的优化第一种类型的启动过程。

2、App启动过程

冷启动的过程就是从用户点击App图标开始,一直到- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法执行完成为止。整个过程可以分为两个阶段,main()函数执行之前和main()函数执行之后。

app_launch_01.png

2.1 main()函数执行之前

  1. 加载可执行文件(App的.o文件集合)
  2. 加载动态链接库,进行rebase指针调整和bind符号绑定
  3. Objc运行时的初始处理,包括Objc相关类的注册、Category注册、selector唯一性检查等
  4. 初始化,包括执行+load()方法、attribute((constructor))修饰的函数调用、创建C++静态全局变量

备注:

  1. rebase指针调整:修复指向当前镜像内部的资源指针。
  2. binding符号绑定:指向镜像外部的资源指针
  3. image 二进制文件,包括可执行文件或so文件,里边是被编译过的符号、代码等。
  4. imageLoader 将image加载进内存,且每一个文件对应一个ImageLoader实例来负责加载。

dyld(动态连接器,the dynamic link editor)是一个专门用来加载动态链接库的库,dyld从可执行文件的依赖开始,递归加载所有依赖的动态链接库。动态链接库包括:iOS中用到的所有系统framework,加载OC runtime方法的libobjc,系统级别的libSystem

相应的,这个阶段对于启动速度优化来说,可以优化的点包含以下几个方面:

  • 减少动态库加载。苹果公司建议使用更少的动态库,如果项目使用的动态库较多,可以将多个动态库合并使用,最多支持6个非系统动态库合为一个。
  • 减少objc类和selector数量,删除启动后不会使用的类或者方法,合并分类文件,删除无用依赖库。
  • 将不必在+load()方法中做的事情延迟到+initialize()方法中。
  • 删减无用静态变量,控制C++全局变量的数量。

2.2 main()函数执行之后

这个阶段是指从main()函数执行开始,到Appdelegate的application:didFinishLaunchingWithOptions:方法执行完成。App的启动逻辑、首屏渲染和业务代码都是在这个阶段,主要包括:

  1. 全局初始化配置,各种组件库的初始化(crash统计、埋点统计)
  2. 首页数据请求、获取和处理
  3. 首页UI计算和渲染

对于第一条,我们要梳理出哪些配置和初始化工作是首屏渲染必要的,哪些是App启动所要求的,除此之外的配置和初始化都分别滞后到合适的阶段执行即可。

优化点:

  • 梳理首屏渲染所不必须的依赖库和功能逻辑,做延迟加载处理,比如放到首页的- (void)viewDidAppear:(BOOL)animated方法中去执行。
  • 在首页控制器的- (void)viewDidLoad- (void)viewWillAppear:(BOOL)animated尽量的减少要做的事情,使首页能够尽快的加载显示出来。
  • 不使用storyboardxib构建首页UI视图,使用纯代码来加载首页。

3、App启动优化

说了这么多,App启动优化的时间如何来衡量呢,这就要用到上面提到的时间T1和T2,下面我们来说下如何来计算T1和T2。

测试使用机器:iPhone 7 Plus,iOS 10.3.2系统,存储容量32GB。

3.1 T1

main()之前的时间T1苹果官方提供了一种方法,在Xcode的Edit Scheme...-->Run-->Arguments选项中设置Environment Variables,添加name为DYLD_PRINT_STATISTICS,Value为1

app_launch_02.png

项目使用真机运行,在控制台就可以看到如下log了。

Total pre-main time: 4.2 seconds (100.0%)
         dylib loading time: 1.9 seconds (46.9%)
        rebase/binding time: 1.6 seconds (39.3%)
            ObjC setup time:  81.78 milliseconds (1.9%)
           initializer time: 498.71 milliseconds (11.7%)
           slowest intializers :
             libSystem.B.dylib :  19.39 milliseconds (0.4%)
                       AppName : 918.63 milliseconds (21.6%)

可以看到Total pre-main time总耗时为4.2秒。

3.2 T2

main()之后到- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions是T2阶段的时间,我们可以采用记住头尾时间取差值的方式得到T2,main函数代码如下:

extern CFAbsoluteTime startTime;

bool isBeauifulStr(char *str);
int main(int argc, char * argv[]) {
    startTime = CFAbsoluteTimeGetCurrent();
    @autoreleasepool {
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MIAppDelegate class]));
    }
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中在最后加入如下代码:

CFAbsoluteTime startTime;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    ...
        
    dispatch_async(dispatch_get_main_queue(), ^{
        NSUInteger ms = (NSUInteger)((CFAbsoluteTimeGetCurrent() - startTime) * 1000);
        NSLog(@"T2 = %lu ms", ms);
    });
 
    return YES;
}

项目启动后,输出结果

T2 = 1190 ms

参考上面的优化点逐条去对启动过程进行优化,然后对比得到的T1和T2的时间,就可以知道你的优化效果到底如何了。

参考

iOS 程序 main 函数之前发生了什么
今日头条iOS客户端启动速度优化
App 启动速度怎么做优化与监控?
优化App的启动时间

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