从腾讯随身测GT源码看APP流畅度测试方法
2016-02-25 本文已影响1729人
白天才痴
腾讯之前分享过一篇测试流畅度原理的文章(http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=208258190&idx=2&sn=22af4f01a6090599da3dca4c44f0f396&scene=2&from=timeline&isappinstalled=0#rd)
GT给出了流畅度的概念,之前普遍认为测试流畅度的值是FPS,但是根据GT的说法,如果一个页面在静止时,他的FTP为0,但此时不能说其是不流畅的。所以GT给出了流畅度概念。
从代码来看其流畅度值为60减去1s内的跳帧数。
下面看看具体工具是怎么做的
流畅度测试核心文件如下:
com.tencent.wstt.gt.plugin.smtools.SMDataService.java
com.tencent.wstt.gt.plugin.smtools.SMLogService.java
GT获取跳帧信息是通过Choreographer输出的log信息获取的,SMLogService就是负责从logcat中筛选这部分log信息
一次完整的跳帧日志如下图:
protected void onHandleIntent(Intent intent) {
try {
String str = intent.getStringExtra("pid");//获取被测app的pid,用于过滤logcat输出的日志,找到被测app的日志
int pid = Integer.parseInt(str);
List<String> args = new ArrayList<String>(Arrays.asList("logcat", "-v", "time", "Choreographer:I", "*:S"));//过滤编舞者输出的log
dumpLogcatProcess = RuntimeHelper.exec(args);
reader = new BufferedReader(new InputStreamReader(dumpLogcatProcess.getInputStream()), 8192);
String line;
while ((line = reader.readLine()) != null && !killed) {//循环读取跳帧日志
// filter "The application may be doing too much work on its main thread."
if (!line.contains("uch work on its main t")) {//过滤出跳帧日志
continue;
}
int pID = LogLine.newLogLine(line, false).getProcessId();
if (pID != pid){
continue;
}
line = line.substring(50, line.length() - 71);
Integer value = Integer.parseInt(line.trim());
SMServiceHelper.getInstance().dataQueue.offer(value);//把解析出的数值添加到一个阻塞列表里。
}
} catch (IOException e) {
Log.e(TAG, e.toString() + "unexpected exception");
} finally {
killProcess();
}
}
同时,另一个核心的类SMDataService就是负责处理这些数据.
线程dataCountThread负责从列表取出跳帧数据并求和。
private Thread dataCountThread = new Thread("SMDataCountThread") {
@Override
public void run() {
while (!pause)
{
try {
int value = SMServiceHelper.getInstance().dataQueue.take();
count.addAndGet(value);//使用AtomicInteger这个类进行求和
} catch (InterruptedException e) {
return;
}
}
}
};
在该service的onHandleIntent中执行循环计算流畅度
while (true) {
if (pause) {
break;
}
int x = count.getAndSet(0);
// 卡顿大于60时,要将之前几次SM计数做修正
if (x > 60) {
int n = x / 60;
int v = x % 60;
TagTimeEntry tte = OpPerfBridge.getProfilerData(key);
int len = tte.getRecordSize();
// 补偿参数
int p = n;//Math.min(len, n);
/*
* n > len是刚启动测试的情况,日志中的亡灵作祟,这种情况不做补偿;
* 并且本次也记为60。本逻辑在两次测试间会清理数据的情况生效。
*/
if (n > len)
{
globalClient.setOutPara(key, 60);
}
else
{
for (int i = 0; i < p; i++) {
TimeEntry te = tte.getRecord(len - 1 - i);
te.reduce = 0;
}
globalClient.setOutPara(key, v);
}
} else {
int sm = 60 - x;//正常情况下的流畅度值
globalClient.setOutPara(key, sm);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
整个工具的实现并不复杂,贵在提出了流畅度的概念,做测试开发就是要通过谷歌提供的工具加上对原理实现的理解做出符合项目需求的工作。