騰訊之前分享過一篇測(cè)試流暢度原理的文章(http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=208258190&idx=2&sn=22af4f01a6090599da3dca4c44f0f396&scene=2&from=timeline&isappinstalled=0#rd)
GT給出了流暢度的概念,之前普遍認(rèn)為測(cè)試流暢度的值是FPS位喂,但是根據(jù)GT的說法,如果一個(gè)頁面在靜止時(shí),他的FTP為0,但此時(shí)不能說其是不流暢的奄容。所以GT給出了流暢度概念泽铛。
從代碼來看其流暢度值為60減去1s內(nèi)的跳幀數(shù)。
下面看看具體工具是怎么做的
流暢度測(cè)試核心文件如下:
com.tencent.wstt.gt.plugin.smtools.SMDataService.java
?com.tencent.wstt.gt.plugin.smtools.SMLogService.java??
GT獲取跳幀信息是通過Choreographer輸出的log信息獲取的如贷,SMLogService就是負(fù)責(zé)從logcat中篩選這部分log信息
一次完整的跳幀日志如下圖:
?
protected void onHandleIntent(Intent intent) {
try {
String str = intent.getStringExtra("pid");//獲取被測(cè)app的pid,用于過濾logcat輸出的日志到踏,找到被測(cè)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) {//循環(huán)讀取跳幀日志
// 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);//把解析出的數(shù)值添加到一個(gè)阻塞列表里杠袱。
}
} catch (IOException e) {
Log.e(TAG, e.toString() + "unexpected exception");
} finally {
killProcess();
}
}
同時(shí),另一個(gè)核心的類SMDataService就是負(fù)責(zé)處理這些數(shù)據(jù).
線程dataCountThread負(fù)責(zé)從列表取出跳幀數(shù)據(jù)并求和窝稿。
private Thread dataCountThread = new Thread("SMDataCountThread") {
@Override
public void run() {
while (!pause)
{
try {
int value = SMServiceHelper.getInstance().dataQueue.take();
count.addAndGet(value);//使用AtomicInteger這個(gè)類進(jìn)行求和
} catch (InterruptedException e) {
return;
}
}
}
};
在該service的onHandleIntent中執(zhí)行循環(huán)計(jì)算流暢度
while (true) {
if (pause) {
break;
}
int x = count.getAndSet(0);
// 卡頓大于60時(shí)楣富,要將之前幾次SM計(jì)數(shù)做修正
if (x > 60) {
int n = x / 60;
int v = x % 60;
TagTimeEntry tte = OpPerfBridge.getProfilerData(key);
int len = tte.getRecordSize();
// 補(bǔ)償參數(shù)
int p = n;//Math.min(len, n);
/*
* n > len是剛啟動(dòng)測(cè)試的情況,日志中的亡靈作祟伴榔,這種情況不做補(bǔ)償;
* 并且本次也記為60纹蝴。本邏輯在兩次測(cè)試間會(huì)清理數(shù)據(jù)的情況生效。
*/
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();
}
}
整個(gè)工具的實(shí)現(xiàn)并不復(fù)雜踪少,貴在提出了流暢度的概念塘安,做測(cè)試開發(fā)就是要通過谷歌提供的工具加上對(duì)原理實(shí)現(xiàn)的理解做出符合項(xiàng)目需求的工作。