在刚接触 iOS 专项测试的时候就开始调研测试 iOS 启动时间,经过一段时间的学习和实践,介绍两种 iOS 启动时间测试的思路.
状态如下:
下图是程序状态变化图:
main 函数之前加载动态库、配置环境等,这个阶段基本上没有开发同学的代码,都是系统的事.
在 main 函数执行之后会走到 ApplicationDelegate 类中,这是开发同学第一个能控制的类.下面介绍几个 ApplicationDelegate 中的回调方法.
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
告诉代理进程启动但还没进入状态保存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
告诉代理启动基本完成程序准备开始运行
- (void)applicationWillResignActive:(UIApplication *)application
当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
- (void)applicationDidBecomeActive:(UIApplication *)application
当应用程序入活动状态执行,这个刚好跟上面那个方法相反
- (void)applicationDidEnterBackground:(UIApplication *)application
当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
- (void)applicationWillEnterForeground:(UIApplication *)application
当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相。
- (void)applicationWillTerminate:(UIApplication *)application
当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。
- (void)applicationDidFinishLaunching:(UIApplication*)application
当程序载入后执行
xcode 提供了一个很赞的方法,只需要在 Edit scheme -> Run -> Arguments 中将环境变量
DYLD_PRINT_STATISTICS 设 1,就可以看到 main 之前各个阶段的时间消耗.
output:
2018-10-08 11:25:41.101432+0800 xxxxxx[2567:1049814] [DYMTLInitPlatform] platform initialization successful
Total pre-main time: 363.78 milliseconds (100.0%)
dylib loading time: 56.61 milliseconds (15.5%)
rebase/binding time: 43.80 milliseconds (12.0%)
ObjC setup time: 50.18 milliseconds (13.7%)
initializer time: 213.00 milliseconds (58.5%)
slowest intializers :
libSystem.B.dylib : 8.25 milliseconds (2.2%)
libBacktraceRecording.dylib : 9.38 milliseconds (2.5%)
libMainThreadChecker.dylib : 13.30 milliseconds (3.6%)
libglInterpose.dylib : 78.40 milliseconds (21.5%)
libMTLInterpose.dylib : 21.70 milliseconds (5.9%)
LuoJiFMIOS : 107.63 milliseconds (29.5%)
这是用打 log 的方式记录时间.
1.首先在 main.m 添加如下代码
CFAbsoluteTime StartTime;
int main(int argc, char * argv[]) {
StartTime = CFAbsoluteTimeGetCurrent();
2.然后在 AppDelegate.m 的开头声明
extern CFAbsoluteTime StartTime;
最后在 AppDelegate.m 的
didFinishLaunchingWithOptions 中第一行添加
OptionsStartTime = CFAbsoluteTimeGetCurrent();
NSLog(@"AppLanuch--mainBefore--%f",(OptionsStartTime - StartTime));
这里统计的是 main 函数之前后到 didFinishLaunchingWithOptions 开始.
最后在 AppDelegate.m 的
didFinishLaunchingWithOptions 中最后一行添加
OptionsEndTime = CFAbsoluteTimeGetCurrent();
NSLog(@"AppLanuch--didOptionsTotal--%f",(OptionsEndTime - OptionsStartTime));
这里是统计这个 didFinishLaunchingWithOptions 函数耗时.
总耗时=main 函数之前 +main 函数之后 +didFinishLaunchingWithOptions
time profile 是 xcode 中 Instruments 中的一个测试工具,可以用来测试函数耗时.
在左侧可以看到每个函数的耗时
使用 appium 启动 app,同时 idevicesyslog 查看 log 日志并找出启动结束的点.这种方案目前我还没有找出确定的结束点,后续再研究下.
启动以后就在 didFinishLaunchingWithOptions 注册各种函数,可以适当把非必须函数置后注册.
会注册第三方 sdk,比如 umeng 和 bugly 等注册会导致耗时的可能,如果更换第三方 sdk,需要对其进行性能测试.
想做好 iOS 专项测试,还是要深入了解 iOS 的一些框架和原理,要不很难深入测试和二次开发.
iOS 应用程序生命周期 (前后台切换,应用的各种状态) 详解
https://blog.csdn.net/totogo2010/article/details/8048652
iOS 启动时间优化
https://mp.weixin.qq.com/s/lRBdtwh7BmO6i3yDBRGTwA
iOS-main 函数之前
https://www.jianshu.com/p/7239f13753aa
如何精确度量 iOS App 的启动时间
https://www.jianshu.com/p/c14987eee107
[iOS] 一次立竿见影的启动时间优化
https://juejin.im/post/5a31190751882559e225a775
iOS App 冷启动治理:来自美团外卖的实践
https://mp.weixin.qq.com/s/jN3jaNrvXczZoYIRCWZs7w
time profile 工具使用
https://www.raywenderlich.com/397-instruments-tutorial-with-swift-getting-started