【 Android 场景化性能测试】启动速度篇

作者:jadefu(傅俊彬)

团队:移动品质中心TMQ

一、背景

传统测试启动速度的方法是录屏分帧,即手工录制启动过程,然后通过分帧软件将启动过程的每一帧抽取出来,选取启动帧与结束帧,从而计算出差值作为启动速度。显然,这个方法有如下缺点:

1、效率低下。

这种简单暴力的操作显然需要耗费人力与大量时间进行测试、数据收集以及分析。

2、数据不准确。

由于一轮测试需要耗费大量时间,所以测试的次数有限,样本量较少,一次异常的数据就有可能会影响最终的结论。既然是简单粗暴重复的劳动,我们是不是可以考虑使用自动化来实现呢?答案是肯定的,我们采用了另一个更为高效准确的方法——读取系统日志获取启动耗时。

下面就来分享一下“懒人的智慧”。

二、日志信息

通过ActivityManager这个TAG,我们可以获取一个Activity的启动耗时。

下面是冷启动(清除数据后启动)的Log信息:

下面是热启动(点击返回键后启动)的Log信息:

可以看到冷启动有两条耗时的日志,这是因为首次安装启动存在闪屏,所以冷启动过程划分成了【点击图标-进入闪屏】以及【闪屏结束后点击按钮-进入应用首页】两个阶段。

通过Log可知:

(1)冷启动耗时为:636ms + 993ms = 1629ms;

(2)热启动耗时为:1520ms

这里需要说明一下,在某些情况下会出现以下类型的Log:

其中前者是This Time,后者是Total Time,关于二者的区别可以参考代码:

这里有三个关键变量,它们各自的定义如下:

(1)curTime:该函数调用时的时间点。

(2)launchTime:一连串启动Activity中最后一个Activity的启动时间点。

(3)mInitialStartTime:一连串启动Activity中第一个Activity的启动时间点。

通常情况下,点击图标只会启动一个Activity,此时launchTime与mInitialStartTime指向同一个时间点,即thisTime=totalTime;但有些应用在启动的时候会启动一个无界面的Activity做逻辑处理,然后再启动一个有界面的Activity,此时launchTime指向有界面Activity的启动时间,mInitialStartTime指向无界面Activity的启动时间,thisTime<totalTime。

如图所示:

05

小结

通过ActivityManager这个TAG可以获取Activity启动耗时。对于单个Activity的启动,我们可直接使用thisTime作为启动耗时;对于多个Activity的启动,我们则使用totalTime作为启动耗时。

三、数据采集

为了实现自动化测试,brookechen编写了一个实现性能自动化测试的框架,通过python和uiautomator驱动用例执行、实现数据收集。关于框架的详细介绍可以参考TMQ系列文章《Android场景化性能测试-方向与框架篇》。

框架大体可分为两个部分:用例执行与数据收集处理,依次执行:

suite_up()、set_up()、test()、tear_down() 、suite_down()。

关于启动速度的用例执行比较简单,在此不赘述,每轮测试包括了冷启动与热启动,主要在test()内执行以下步骤:

清除数据-启动应用-滑动闪屏进入首页-返回桌面-再次启动应用。

而数据的收集,会在set_up()方法内开启一个线程收集数据,通过adb命令:

logcat -v time ActivityManager:I *:S

我们可以只收集ActivityManager这个TAG的日志,但是这个日志除了我们需要获取的耗时信息,还有其他一些启动相关的日志,在这里我们还需对日志做进一步的筛选过滤,具体规则如下:

(1)不含Displayed的日志行丢弃;

(2)不含指定包名的日志行丢弃;

(3)不含指定Activity名的日志行丢弃。

获取了有用的日志行之后,我们还需要对日志行提取出启动耗时的数据,即从09-26 19:57:03.332: I/ActivityManager(932): Displayed com.tencent.wifimanager/com.tencent.server.fore.QuickLoadActivity: +944ms提取出 944ms,这里我们可以通过正则表达式来获取,具体代码如下:

四、数据分析

有了自动化脚本,我们就可以对历史版本的启动速度做一个对比,并将测试数据以折线图的形式直观地展示出来,从而更直接地反映不同版本启动速度的差异。

得出测试数据后,若测试结论不理想,我们可以通过Android Device Monitor的trace viewer来观察不同线程及不同方法的执行耗时。

对于上半部分的图表,我们主要关注不同线程占用的耗时,颜色横条越长越多,表示该线程占用耗时越大。

对于下半部分的表格,我们主要关注对应线程下不同方法的占用耗时,主要关注以下三个字段:

(1)Cpu Time/Call:该方法平均占用 CPU 的时间;

(2)Real Time/Call:该方法平均执行时间,包括切换、阻塞的时间;

(3)Calls+RecurCalls/Total:该方法调用、递归次数。

以上三个字段数值越大,表示方法占用耗时越大。

为了方便开发定位,我们还可以将生成的traceview文件提供给开发,具体的目录可以将鼠标放到traceview名称上,对应的目录就会显示出来。

至此,启动速度数据的收集以及分析已经介绍完毕,水平有限,无法一一详尽,阅读过程中有任何的疑问或修正都欢迎随时提出,一同讨论。

搜索微信公众号:腾讯移动品质中心TMQ,获取更多测试干货!

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯Bugly的专栏

Android 开发必备知识:我和 Gradle 有个约会

0、讲个故事 0.1 Ant,我还真以为你是只蚂蚁 真正开始近距离接触编程其实是在2012年,年底的时候带我的大哥说,咱们这个 app 发布的时候手动构建耗时太...

3374
来自专栏Golang语言社区

深入理解Wi-Fi P2P

本章主要内容: 介绍Wi-Fi P2P相关知识; 介绍Android中WifiP2pService、wpa_supplicant的相关代码。 7.1 概述 承...

3343
来自专栏李想的专栏

使用腾讯云无服务器云函数(SCF)分析天气数据

无服务器云函数(SCF)是腾讯云提供的Serverless执行环境,也是国内首款FaaS(Function as a Service,函数即服务) 产品。其核心...

8517
来自专栏Spark学习技巧

SparkStreaming如何解决小文件问题

2192
来自专栏SDNLAB

SDNLAB技术分享(一):ODL的Service Function Chaining入门和Demo

在网络通信过程中,包含各式各样的网络服务功能。既可以包含传统的像防火墙,NAT等功能,也有包含特定的网络应用功能(Service Function)。将特定的网...

3689
来自专栏数据和云

Oracle12.2体系架构图:Filesystem+Multitenant

全面解读Oracle 12.2体系架构图系列课程,精彩继续。本期的内容由两部分组成,一是数据库实例与文件系统的访问;二是多租户解决方案。文中将会简单列举视频要点...

3289
来自专栏腾讯Bugly的专栏

【Dev Club 分享】微信mars 的高性能日志模块 xlog

Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师。每周都会举行嘉宾分享,话题讨论等活动。 本期,我们邀请了 ...

5025
来自专栏程序猿的那些趣事

七夕快到了!表白小程序制作详解,撩翻你的女神!

大家可能都会在抖音上刷过,那种表白小程序,但在我看来表白还是亲口说出来比较好,这类小程序只适合在平常的一些小节日给对方一个惊喜。话不多说,现在进入正题:

651
来自专栏吉浦迅科技

DAY73:阅读Programming Guidelines

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第73天,我们正在讲解CUDA 动态并行,希望在接下来的27天里,您可以...

663
来自专栏编程

如何扩展一个自定义SOP节点

平安夜祝大家平平安安,以后的文章关于C++语言方面的内容会多一些,不太理解的话就当一乐子看,了解一下Houdini底层架构知识也是好的。能保证的是文章的内容都是...

2056

扫码关注云+社区