iOS 测试 iOS 启动时间测试

xinxi · 2018年12月11日 · 最后由 leonhart 回复于 2018年12月25日 · 最后更新自管理员 陈恒捷 · 3735 次阅读
本帖已被设为精华帖!

前言

在刚接触iOS专项测试的时候就开始调研测试iOS启动时间,经过一段时间的学习和实践,介绍两种iOS启动时间测试的思路.

iOS应用生命周期

状态如下:

  • Not running: 未运行 程序没启动
  • Inactive: 未激活 程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态
  • Active: 激活 程序在前台运行而且接收到了事件。这也是前台的一个正常的模式
  • Backgroud: 后台 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态
  • Suspended: 挂起 程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。

下图是程序状态变化图:

image

iOS app启动过程

main函数之前

main函数之前加载动态库、配置环境等,这个阶段基本上没有开发同学的代码,都是系统的事.

image

main函数之后

wx20181211-160723.png

  • 1.执行UIApplicationMain函数
  • 2.创建Application对象,创建ApplicationDelegate,并设为Application的代理
  • 3.创建RunLoop主循环,代理开始监听事件
  • 4.启动完毕后会执行didFinishLaunching,创建keyWindow,以及weindow的跟视图控制器
  • 5.显示窗口

ApplicationDelegate

在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
当程序载入后执行

测试

main函数之前测试

xcode提供了一个很赞的方法,只需要在 Edit scheme -> Run -> Arguments中将环境变量
DYLD_PRINT_STATISTICS设 1,就可以看到 main 之前各个阶段的时间消耗.

image

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%)

main函数之后测试

这是用打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开始.

didFinishLaunchingWithOptions测试

最后在AppDelegate.m 的
didFinishLaunchingWithOptions中最后一行添加

OptionsEndTime = CFAbsoluteTimeGetCurrent();
NSLog(@"AppLanuch--didOptionsTotal--%f",(OptionsEndTime - OptionsStartTime));

这里是统计这个didFinishLaunchingWithOptions函数耗时.

image

统计启动耗时

总耗时=main函数之前+main函数之后+didFinishLaunchingWithOptions

time profile工具

time profile是xcode中Instruments中的一个测试工具,可以用来测试函数耗时.

time profile

image

启动app

image

main方法

image

函数列表

在左侧可以看到每个函数的耗时
image

点击函数

image

跳转到具体函数

image

自动化方案测试

使用appium启动app,同时idevicesyslog查看log日志并找出启动结束的点.这种方案目前我还没有找出确定的结束点,后续再研究下.

踩坑

在didFinishLaunchingWithOptions中注册函数太多

启动以后就在didFinishLaunchingWithOptions注册各种函数,可以适当把非必须函数置后注册.

在didFinishLaunchingWithOptions中使用第三方sdk

会注册第三方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

共收到 7 条回复 时间 点赞

大佬能请教个问题么?
关于appium ios自动化的~ noReset参数 设置为False的时候,应该是会去重置应用的,
我用模拟器的时候没问题 可以重置,但是真机测试的时候 没有反应 不会去重置~ 能不能帮忙分析下可能是哪里有问题?

fhvch 回复

Shut down sim after test. Do not destroy sim. Do not uninstall app from real device. 官网的解释...

xinxi 回复

我好像知道问题所在了 谢谢
大佬,那我再问个问题,
Android的noReset参数为fasle的时候 是去清理应用 应该就是去执行了一个pm clear 的命令
ios的 noReset参数为fasle,我之前用ios模拟器的时候 好像是去重新安装了一次这个应用
真机可能是我刚刚没有设置 app这个参数 就没有找到安装包 就没有去重新安装了~
除了 它这个重新安装的方法之外 还有没有别的办法去到达重置应用的效果

fhvch 回复

google了一番,iOS没有清除数据缓存的命令

陈恒捷 将本帖设为了精华贴 12月18日 23:13

加精理由:从原理到具体方法,讲得挺完整,而且也有相关的参考资料。

PS:印象中 wwdc 中有相关的 topic 专门讲启动时间的,建议也补充到参考资料里,更为完整。

看懂了赞

安涛 定向班第一期_shell 课程实战_20181216 中提及了此贴 12月21日 16:29

有头无尾,期待后续更新

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册