【OC性能优化】App启动优化

目录

理论
一、App启动流程及可能导致App启动变慢的原因
二、App启动优化

实操
三、监测App启动耗时及定位导致App启动变慢的耗时代码


一、App启动流程及可能导致App启动变慢的原因


要想做App启动优化,就得先知道可能导致App启动变慢的原因,要想知道可能导致App启动变慢的原因,就得先知道App启动流程。

App启动分两种:冷启动和热启动。冷启动是指启动一个杀死的App,系统需要为App开辟一个新进程,热启动是指启动一个在后台运行的App,App的进程还存活着,系统不需要开辟新进程。而我们通常所说的App启动优化,主要是指冷启动优化——尽可能地缩短启动时间,所以接下来本文中谈到的启动都是指冷启动。

App启动流程主要分为两大阶段:main函数调用前的阶段和main函数调用至didFinishLaunchingWithOptions方法执行完毕的阶段。

1、main函数调用前的阶段

  • App启动后,系统会首先加载项目的可执行文件和依赖的动态库到内存中。
  • 然后系统会调用Runtime的函数对项目的可执行文件进行解析和处理,把项目中所有的类和分类加载到内存中,此时会调用项目中所有类和分类的+load方法。

2、main函数调用至didFinishLaunchingWithOptions方法执行完毕的阶段

  • 系统会调用main函数、UIApplicationMain函数、AppDelegatedidFinishLaunchingWithOptions方法,我们通常会在这个方法里给window设置rootViewController,不过我们要知道只有rootViewController或者rootViewController首屏的viewDidLoad方法和viewWillAppear方法走完了,才算rootViewController设置完毕。
  • rootViewController设置完毕,我们通常还会在这个方法里为App添加一些必要的启动项,didFinishLaunchingWithOptions方法走完了就代表App启动起来了,此时系统才会去调用rootViewController或者rootViewController首屏的viewDidAppear方法,这是后话了。

如果这两个阶段的环节做了太多的工作,就可能导致App启动变慢。


二、App启动优化


所以我们做App启动优化,主要就是从减少这两个阶段的环节的工作入手。

1、main函数调用前的阶段

  • 尽量减少动态库的使用,定期清理掉不必要的动态库;
  • 尽量减少类和分类的数量,定期清理掉不必要的类和分类;尽量减少类和分类+load方法的调用,不要在里面做复杂的操作,可以用+initialize方法和dispatch_once替代,因为+initialize方法是初始化类和分类时才调用的,也就是说+initialize方法项目里确确实实用到这些类和分类时才会调用的,而+load方法不管你用不用这些类和分类都会调用。

2、main函数调用至didFinishLaunchingWithOptions方法执行完毕的阶段

  • rootViewController或者rootViewController首屏的viewDidLoad方法和viewWillAppear方法里尽量只做一些关键数据的初始化和绘制UI操作,不要做别的耗时操作,如果非做不可,就放到子线程里去做。
  • 启动项最好按需配置,不需要在App一启动就配置的启动项可以推迟到使用时再配置,必须配置的启动项如果很耗时,就放到子线程里去做。


三、监测App启动耗时


1、main函数调用前的阶段

Xcode --> Target --> Edit Scheme --> Run --> Arguments --> Environment Variables,添加DYLD_PRINT_STATISTICS = YES,400ms以内就算正常。

运行项目,控制台就会打印pre-main阶段的启动耗时了。

我们添加一个ARKit动态库。

我们再添加很多类和分类。

我们再调用一下某个类的+load方法,里面休眠2s模拟耗时操作。

2、main函数调用至didFinishLaunchingWithOptions方法执行完毕的阶段

Xcode --> Project --> Target --> Build Settings --> dsym --> Debug Information Format --> 都设置为DWARF with dSYM File,否则Time Profiler显示出来的都是函数的内存地址而不是函数名。
InstrumentsTime Profiler
  • Xcode打开项目,连接真机(一定要用真机调试,因为模拟器用的是电脑的CPU,检测不出手机的启动耗时来)。
  • 打开InstrumentsTime Profiler
  • 选择真机、选择项目、运行、定量地监测App启动耗时,并定位耗时代码。
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self.window setBackgroundColor:[UIColor whiteColor]];
    [self.window makeKeyAndVisible];
    
    [self.window setRootViewController:[[ViewController alloc] init]];
    
    return YES;
}


// ViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
}

我们在rootViewControllerviewDidLoad方法和viewWillAppear方法里添加一些耗时操作。

// ViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self doSomething];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    [self doSomething];
}


#pragma mark - 模拟耗时操作

- (void)doSomething {
    
    for (int i = 0; i < 200000; i++) {
        
        NSLog(@"%d", i);
    }
}
可见Test项目的总启动耗时为2.92s,其中“main函数调用至didFinishLaunchingWithOptions方法执行完毕阶段”耗时2.66s,而导致耗时这么长的原因就是rootViewController的viewDidLoad方法和viewWillAppear方法里的doSomething方法,我们可以对它进行优化

我们再在rootViewController设置完毕、didFinishLaunchingWithOptions方法执行完毕之前添加一些耗时操作。

// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self.window setBackgroundColor:[UIColor whiteColor]];
    [self.window makeKeyAndVisible];
    
    [self.window setRootViewController:[[ViewController alloc] init]];
    
    [self doSomething];
    
    return YES;
}


#pragma mark - 模拟耗时操作

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

推荐阅读更多精彩内容