如果一個(gè)android應(yīng)用打開時(shí)比較慢,或者使用起來(lái)比較卡。這個(gè)可能是客戶端代碼有待優(yōu)化,也可能是服務(wù)端性能比較挫。對(duì)一個(gè)客戶端開發(fā)者而言,在客戶端代碼中增加相關(guān)debug日志,即可比較準(zhǔn)確地定位問(wèn)題。但這活要落到一個(gè)服務(wù)端開發(fā)人員手里,要怎么辦?
本文將在沒有apk源碼的情況下,以服務(wù)端開發(fā)人員的視角進(jìn)行客戶端app性能的分析。
在分析之前,我們先補(bǔ)充點(diǎn)android基礎(chǔ)知識(shí)。
我們所說(shuō)的android應(yīng)用,一般都是通過(guò)將一個(gè)以apk結(jié)尾的文件安裝在手機(jī)等移動(dòng)設(shè)備上才能運(yùn)行起來(lái)的。所以我們先從apk說(shuō)起。
我們先從網(wǎng)上下載一個(gè)apk
$ wget http://shouji.360tpcdn.com/131106/0124832c4cf8c35a762cfece3bac52b1/com.sina.weibo_650.apk
然后查看這個(gè)文件的類型
$ file com.sina.weibo_650.apkcom.sina.weibo_650.apk: Zip archive data, at least v2.0 to extract
會(huì)發(fā)現(xiàn)com.sina.weibo_650.apk
是一個(gè)zip壓縮文件。解壓縮后的文件,主要包括一些資源文件,一些配置文件,一些類庫(kù),還有一個(gè)class.dex。目錄結(jié)構(gòu)如下
AndroidManifest.xmlassetsclasses.dexlibMETA-INForgresresources.arsc
粗略一看,發(fā)現(xiàn) class.dex
這個(gè)文件有5.9M,這應(yīng)該就是主角。繼續(xù)執(zhí)行如下命令
$ file classes.dexclasses.dex: Dalvik dex file version 035
因?yàn)闆]有開發(fā)過(guò)android應(yīng)用,不明白用java開發(fā)的app和這個(gè)Dalvik dex file之間有什么關(guān)系?所以我們先跳出apk的視角。
如上圖,android基于linux操作系統(tǒng),使用linux內(nèi)核與設(shè)備的硬件進(jìn)行交互。在內(nèi)核之上,又抽象出了一層,包括Dalvik虛擬機(jī)等。
因?yàn)?code style="margin: -1px 0px; padding: 0px 0.3em; border: 1px solid rgb(221, 221, 221); font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace; font-style: inherit; font-variant: inherit; line-height: 1.5em; font-size: 0.8em; vertical-align: baseline; display: inline-block; color: rgb(85, 85, 85); border-top-left-radius: 0.4em; border-top-right-radius: 0.4em; border-bottom-right-radius: 0.4em; border-bottom-left-radius: 0.4em;">dex是Dalvik VM
Executes的全稱,即android Dalvik
虛擬機(jī)執(zhí)行程序。
那一個(gè)apk的生產(chǎn)和執(zhí)行過(guò)程將是: *.java -> *.class -> classes.dex(classes.dex將由Dalvik VM轉(zhuǎn)換成機(jī)器碼,由linux內(nèi)核交給cpu去執(zhí)行)
這樣的話,在linux系統(tǒng)上使用profile軟件的經(jīng)驗(yàn),也將派上用場(chǎng)。
android相關(guān)基礎(chǔ)知識(shí)先介紹到此,感興趣的請(qǐng)進(jìn)一步查閱本文后面的參看資料。
在分析之前,我們先看看android程序的執(zhí)行流程
如上圖,只要獲取到啟動(dòng)ActivityManager所需要的時(shí)間,即是apk的啟動(dòng)時(shí)間。
adb logcat | grep ActivityManager
其中”Displayed”對(duì)應(yīng)的時(shí)間,即是launch Activity對(duì)應(yīng)的時(shí)間,也就是apk啟動(dòng)時(shí)間,也可以使用如下命令:
adb logcat -c && adb logcat -s ActivityManager | grep "Displayed"
adb
,需要先用usb線連接電腦和手機(jī),并在手機(jī)的設(shè)置
–>開發(fā)者選項(xiàng)
中開啟USB調(diào)試
adb
這個(gè)工具,可以通過(guò)在android sdk的platform-tools目錄中找到。后面介紹的systrace
也在這個(gè)目錄。android應(yīng)用中的頁(yè)面,是由android系統(tǒng)一幀,一幀地繪制的,其中每一幀的處理如下圖:
即: 計(jì)算視圖大小(measure) -> 安置視圖的位置(layout) -> 繪制(draw)視圖
通過(guò)收集每幀的處理時(shí)間,即可以了解頁(yè)面的渲染性能。
當(dāng)fps(每秒處理幀數(shù),頁(yè)面刷新率)為60時(shí),頁(yè)面的渲染看起來(lái)會(huì)比較平滑,這就需要每幀的處理時(shí)間不能大于16ms(1000/60)
要檢測(cè)一個(gè)應(yīng)用在渲染頁(yè)面時(shí)的每幀處理時(shí)間,通過(guò)如下命令,即可獲得每幀的處理時(shí)間
adb shell dumpsys gfxinfo com.sina.weibo
在輸出日志的Profile
數(shù)據(jù)段,包含了三列Draw
,Process
,Execute
分別對(duì)應(yīng)的處理時(shí)間,單位是ms。這三列的總和,就是渲染每幀時(shí)的處理時(shí)間。如
Draw Process Execute0.95 0.93 0.720.84 1.16 0.560.83 0.89 0.691.32 2.15 1.141.29 1.37 1.01
在進(jìn)行分析之前,需要在
設(shè)置
–>開發(fā)者選項(xiàng)
中點(diǎn)擊GPU呈現(xiàn)模式分析
,選擇在adb shell dumpsys gfxinfo中
。
收集步驟:
1.重新啟動(dòng)app2.在界面完全加載完之后,在界面上慢慢上下滑動(dòng)幾個(gè)像素3.在終端執(zhí)行adb shell dumpsys gfxinfo com.sina.weibo
這時(shí)將在終端輸出頁(yè)面渲染時(shí)的最后128幀中每幀所花費(fèi)的時(shí)間,將相關(guān)數(shù)據(jù)貼到excel表格中,點(diǎn)擊其中的insert
–>chart
,即可生成相關(guān)圖表
其中
com.sina.weibo
就是app的包名
獲取包名的方法:
adb shell pm list packages
通過(guò)收集該apk的啟動(dòng)速度和每幀的渲染時(shí)間,并與竟品進(jìn)行對(duì)比發(fā)現(xiàn)。該app啟動(dòng)時(shí)間的確比較慢,也偶爾有丟幀的現(xiàn)象發(fā)生。如何近一步分析呢?這時(shí)就需要systrace
了。
示例使用方法如下:
cd android-sdk-linux/platform-tools/systracepython systrace.py --app=com.qihoo.appstore gfx view
上面這條命令將會(huì)在android-sdk-linux/platform-tools/systrace
目錄下生成trace.html
。其中收集了包名為com.qihoo.appstore
的應(yīng)用在android系統(tǒng)上針對(duì)gfx
和view
category的執(zhí)行數(shù)據(jù)。
trace.html
在瀏覽器中打開如下圖:
可以使用如下方法,對(duì)trace.html
進(jìn)行進(jìn)一步分析: * 通過(guò)鼠標(biāo)點(diǎn)擊左側(cè)的+
,-
可以展開或者收縮相關(guān)顯示數(shù)據(jù) * 通過(guò)鍵盤上的a
,d
可以使顯示的內(nèi)容沿著頂部的時(shí)間軸向左或者向右移動(dòng) * 通過(guò)鍵盤上的w
,s
可以對(duì)顯示的內(nèi)容進(jìn)行放大或者縮小 * 使用鼠標(biāo)點(diǎn)擊內(nèi)容頁(yè)面的某一個(gè)塊,在下方會(huì)顯示詳情 * 使用鼠標(biāo)選擇一塊內(nèi)容頁(yè)面,在下方會(huì)顯示匯總信息
將光標(biāo)定位到最后一行,使用w
進(jìn)行放大,使用d
向左移動(dòng)到2260ms左右,如下圖:
發(fā)現(xiàn)對(duì)于那些performTraversals
處理超過(guò)16ms的幀,其中eglSwapBuffers
處理的時(shí)間都比較長(zhǎng),這應(yīng)該就是問(wèn)題所在。
使用usb線連接上手機(jī),在命令行下運(yùn)行:
python systrace.py -h
可以查看相關(guān)使用方法。
systrace是在在android4.1上新增的工具,在4.1,4.2和4.3上使用的方法不同
聯(lián)系客服