计算app启动时间(OC,Swift)

App启动时间,直接影响用户对app的第一体验和判断.如果启动时间过长,不单用户体验会下降, 还有可能会触发苹果的watch dog机制而kill掉App, 所以App启动时间优化也十分重要

App启动流程

App的启动如下图所示:
image

那么App的启动时间大致可分为两部分, 第一部分为main函数执行之前的加载时间主要是系统的动态链接库和可执行文件的加载时间;第二部分是main函数开始到 application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions执行结束前的时间

main函数以前消耗的时间(pre-main)

首先需要在scheme中添加配置, 如下图

image

然后启动App就能在控制台看到如下信息, 时间消耗的项目十分明显, 如下所示:

Total pre-main time: 2.6 seconds (100.0%)
         dylib loading time: 1.8 seconds (70.4%)
        rebase/binding time: 535.42 milliseconds (20.2%)
            ObjC setup time:  47.95 milliseconds (1.8%)
           initializer time: 200.64 milliseconds (7.5%)
           slowest intializers :
                  AFNetworking : 158.25 milliseconds (5.9%)

main函数有花费的时间

面函数以后花费的时间主要是从main函数开始到 application:didFinishLaunchingWithOptions:之间的时间, 方法如下:

main函数中记录时间的起点

#import 
#import "AppDelegate.h"
CFAbsoluteTime appStartLaunchTime;
int main(int argc, char * argv[]) {
    @autoreleasepool {
        appStartLaunchTime = CFAbsoluteTimeGetCurrent();
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

application: didFinishLaunchingWithOptions:中记录时间的终点, 取两者之差即可

extern CFAbsoluteTime appStartLaunchTime;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"app启动时间%f", CFAbsoluteTimeGetCurrent() - appStartLaunchTime);
    });
    //....
    return YES;
}
@end

如何减少main()调用之前的耗

  1. 减少不必要的framework,特别是第三方的,因为动态链接比较耗时

  2. check framework应设为optional和required,如果该framework在当前App支持的所有iOS系统版本都存在,那么就设为required,否则就设为optional,因为optional会有些额外的检查;

  3. 合并或者删减一些OC类

  4. 删减一些无用的静态变量

  5. 删减没有被调用到或者已经废弃的方法

  6. 将不必须在+load方法中做的事情延迟到+initialize中

Swift如何计算启动时间

Swift项目是没有main文件,官方给了如下解释:

@UIApplicationMain to a regular Swift file. This causes the compiler to synthesize a mainentry point for your iOS app, and eliminates the need for a “main.swift” file.

也就是说,通过添加@UIApplicationMain标志的方式,帮我们添加了mian函数了。所以如果是我们需要在mian函数中做一些其它操作的话,需要我们自己来创建main.swift文件,这个也是苹果允许的。

  • 注释掉AppDelegate类中的 @UIApplicationMain标志;

  • 自行创建main.swift(注意:main一定要小写, 不能写成Main否则报错)文件,并添加程序入口, 代码如下:

      import UIKit
      
      var appStartLaunchTime: CFAbsoluteTime = CFAbsoluteTimeGetCurrent()
      
      UIApplicationMain(CommandLine.argc, UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer.self,capacity: Int(CommandLine.argc)), nil, NSStringFromClass(AppDelegate.self))
    
  • 然后在AppDelegate中编写如下代码:

      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
          // Override point for customization after application launch.
          // APP启动时间耗时,从mian函数开始到didFinishLaunchingWithOptions方法结束
          DispatchQueue.main.async {
              print("APP启动时间耗时,从mian函数开始到didFinishLaunchingWithOptions方法:\(CFAbsoluteTimeGetCurrent() - appStartLaunchTime)。")
          }
          return true
      }

你可能感兴趣的:(计算app启动时间(OC,Swift))