【穿山甲系列】找出后台偷偷耗电的元凶

作者:万宇

团队:腾讯移动品质中心TMQ

背景故事

先来看一个浏览器用户反馈。

如图所示,在浏览器用户反馈中,耗电一直是头部问题之一,用户对于电量是非常敏感的,特别是那种类似“我明明就没用,怎么还在耗电?”的后台耗电问题,更容易引起用户的抱怨。

遇到这些情况,项目组和测试组都比较无奈。我们明明一直都有做耗电测试,本地的耗电监控也一直跑的很溜。但是线上仍然有这些问题,应该怎么办呢?

所以,我们需要一种新的耗电监控的方案,来解决线上用户反馈的耗电问题。

方案分析

对于线上用户耗电的监控,我们需要解决两个问题。

1、线上用户不同于本地测试,不可能随时把手机拿到进行调试,我们如何在app端获取足够的信息,以方便后期的调试分析?

2、线上用户数量庞大,不像本地测试才个位数的机器,这么多用户,手工分析太耗时,我们如何进行自动化分析?

先考察一下现有的耗电监控的方案:

测试方法一:BatteryHistorian(https://github.com/google/battery-historian)

Battery Historian是Google推出的专用来分析Android App耗电的工具,通过简单的操作便可在网页中生成比较详细的图表,展示手机上各模块电量消耗情况。我们主要用Battery Historian来做定期的例行测试,并以邮件的形式同步测试结果。

BatteryHistorian报表

测试方法二:Method Profiling

针对常见的用户场景,在浏览器切后台时通过DDMS Method Profiling抓取后台执行的所有任务。Method Profiling一般是用来分析性能问题的,它会记录每一个线程、每一个方法的耗时,也正是利用了这一点,我们可以清楚地看到浏览器在切后台后都做了哪些事情。

对比两种方案, 最终我们选择了基于后台Method Profiling方案,因为这个方案有两个优点。

1、MethodProfiling在用户手机上容易执行, 调用一个函数抓trace即可, 而Battery Historian需要执行shell命令。

2、MethodProfiling有更加丰富的函数执行信息, 而Battery Historian只能够获取一些系统事件。

技术实现

线上监控别于本地测试,本地测试可以简单粗暴,但在用户的手机上,必须考虑方案对用户的影响。Method Profiling生成的Trace文件相对来说是比较大的,最大可能有几十兆,我们不可以把所有用户的Trace文件都上报上来。

另外,监控本身可能导致耗电,例如我们首先排除的方案——用一个例行线程不断记录当前所有线程,所以在设计方案时需要将监控本身的影响降到最低。

几轮讨论后,我们最终采用了这样的思路——首先监控是否存在后台耗电现象,当判断为后台耗电现象后开始Method Profiling并通过穿山甲上报。

这样我们上报的都是经过筛选的有问题的场景,一方面减轻了后台数据存储的压力,另一方面也相当于做了过滤,减轻后台分析的工作量。

最终线上耗电监控的具体方案如下:

1、切后台时,记录当前进程对CPU占用的时间片;

2、切后台一段时间后,再获取进程对CPU占用的时间片,如果发现耗电异常,开始Method Profiling;

3、MethodProfiling进行一段时间后停止,上报trace文件到穿山甲后台;

4、穿山甲后台对上报的trace文件进行分析和处理,并自动提BUG单。

关键技术点一:判断耗电异常

APP耗电的产生主要是对CPU产生了占用,我们通过获取浏览器占用CPU时间片的数据来判断是否异常耗电。在Linux系统中,可以通过/proc//stat查看进程对CPU的占用数据。

打印的第14~17个参数依次表示(单位:jiffies):

114242 utime,任务在用户态运行的时间

20692 stime,任务在核心态运行的时间

6 cutime,累计的任务的所有的waited-for进程曾经在用户态运行的时间

2 cstime,累计的任务的所有的waited-for进程曾经在核心态运行的时间

Jiffies是Linux内核中代表时间的变量。系统中定义了一个常数HZ,代表每秒种最小时间间隔的数目,jiffies的单位就是1/HZ。每个CPU时间片,jiffies都要加1。进程的CPU时间片占用就是用户态+系统态的jiffies,进程占用的jiffies越大,对CPU的占用越多。

114242 + 20692+ 6 + 2 = 134942 (jiffies)

在浏览器切后台时,记录当前进程占用的jiffies,当切后台达到设定时间后(10分钟),再次获取当前占用的jiffies,当两次差值超过设定阀值时(400jiffies),判定为发生了后台耗电事件。阈值设定参考了手机厂商后台耗电的评判标准。

关键技术点二:上报分析

当判定后台耗电后,开始抓取Trace,时长1分钟,Trace结束上报数据到后台。

正式版用户数庞大,我们上报的trace文件相对来说比较大,如果正式版做监控上报数据量会相当庞大, 目前资源无法支持。当存在耗电场景时,抽取一部分用户应该也是可以监控到的,所以我们选取一部分内测版的用户做监控和上报耗电异常。另外为了避免消耗用户流量,我们只会在WiFi环境下上报数据。

当存在耗电问题时,上报上来的trace文件会比较多,我们不可能每一个上报都做人工分析处理,所以需要一个程序来进行自动化的分析。

对trace数据文件的分析参考了TraceView源代码,主要是对Metho Profiling文件格式的解析。从Method Profiling数据中我们可以得出当次上报有多少个线程在运行,每个线程里都调用了哪些方法,以及每个方法的调用栈、耗时等。

有了方法的耗时, 调用栈等信息, 是不是就可以确定问题了?

一个耗时长的调用栈, 是不是就是耗电的元凶呢?

答案:并不是!

根据历史经验, 一个孤立的调用栈, 就算它比较耗时,但很多时候并不是耗电问题的元凶. 真正的耗电原因, 常常是一些定时任务, 浏览器切后台以后本应该停止, 但这些任务还一直在执行, 导致耗电量大, 而这些调用栈, 具有下面一些特征:

(1)多次被调用;

(2)调用具有规律性;

(3)调用比较耗时。

所以,我们从trace文件中,对每个调用栈,分别计算下面3个指标。

1)调用次数,记为count;

2)调用时间间隔的方差, 记为diviation;

3)运行耗时, 记为cost。

针对每一个调用栈, 我们给出一个评分:

Score = cost * count / diviation

分数越大的调用栈,越可能是耗电问题。同时,我们把类似的栈进行合并,上报次数越多的调用栈,影响面越广。最终,我们根据排序,将Top50的调用栈标记为疑似耗电问题,自动提交Bug。

Trace源文件


最终Bug信息:

分析结果:

实施效果

以下是从引入线上电量监控以来的相关数据统计。

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

版权所属,禁止转载

你可能感兴趣的:(精准测试)