開(kāi)發(fā)應(yīng)用的時(shí)候,,應(yīng)該檢查它是否有流暢的用戶體驗(yàn),即60fps的幀率,。如果由于某種原因丟幀,,我們首先要做的就是知道系統(tǒng)在做什么(造成丟幀的原因)。 Systrace允許你監(jiān)視和跟蹤Android系統(tǒng)的行為(trace),。它會(huì)告訴你系統(tǒng)都在哪些工作上花費(fèi)時(shí)間,、CPU周期都用在哪里,甚至你可以看到每個(gè)線程、進(jìn)程在指定時(shí)間內(nèi)都在干嘛,。它同時(shí)還會(huì)突出觀測(cè)到的問(wèn)題,,從垃圾回收到渲染內(nèi)容都可能是問(wèn)題對(duì)象,,甚至提供給你建議的解決方案,。本文章將介紹如何導(dǎo)出trace以及使用它來(lái)優(yōu)化UI的辦法。 總覽Systrace可以幫助你分析應(yīng)用在不同Android系統(tǒng)上的運(yùn)行情況,。它將系統(tǒng)和應(yīng)用的線程運(yùn)行情況放置在同一條時(shí)間線上分析,。你首先需要收集系統(tǒng)和應(yīng)用的trace(后面會(huì)告訴你怎么做),之后Systrace會(huì)幫你生成一份細(xì)致,、直觀的報(bào)告,,它展示了設(shè)備在你監(jiān)測(cè)的這段時(shí)間內(nèi)所發(fā)生的事情。 圖1. 連續(xù)滑動(dòng)應(yīng)用5秒的Trace,,它并沒(méi)有表現(xiàn)得很完美,。 圖1展示了應(yīng)用在滑動(dòng)不流暢的時(shí)候生成的trace。默認(rèn)縮放成全局顯示,,你可以放大到自己所關(guān)注的地方,。橫軸代表著時(shí)間線,事件記錄按照進(jìn)程分組,,同一個(gè)進(jìn)程內(nèi)按線程進(jìn)行縱向拆分,,每個(gè)線程記錄自己的工作。 在本例中,,一共有三個(gè)組:Kernel, SurfaceFlinger, App,,他們分別以包名為標(biāo)識(shí)。每個(gè)應(yīng)用進(jìn)程都會(huì)包含其中所有線程的記錄信號(hào),,你可以看到從InputEvent到RenderThread都有,。 生成Trace在獲取trace之前需要做一些啟動(dòng)工作。首先,,設(shè)備要求API>=16(Android 4.1),,之后通過(guò)正常的Debug流程(開(kāi)啟調(diào)試、連接工作環(huán)境,、安裝App)連接設(shè)備,。由于需要記錄磁盤(pán)活動(dòng)和內(nèi)核工作,你可能需要root權(quán)限,。不過(guò)大部分時(shí)候你只要能夠正常Debug即可,。 Systrace 可以通過(guò) 命令行 或者 圖形界面 啟動(dòng),本篇文章重點(diǎn)介紹通過(guò)命令行使用Systrace,。 在Android 4.3及以上的系統(tǒng)中獲取trace在4.3以上的系統(tǒng)獲取Trace步驟:
$ cd android-sdk/platform-tools/systrace $ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm $cdandroid-sdk/platform-tools/systrace $pythonsystrace.py--time=10-omynewtrace.htmlschedgfxviewwm
你可以通過(guò) Systrace選項(xiàng) 來(lái)了解更多命令行選項(xiàng)。 在Android 4.2及以下的系統(tǒng)中獲取trace在4.2及以下的系統(tǒng)中高效地使用Systrace的話,,你需要在配置的時(shí)候顯式指定要trace的進(jìn)程種類,。一共有這兩類種類:
你可以通過(guò)以下命令行操作來(lái)設(shè)置tags:
$ cd android-sdk/platform-tools/systrace $ python systrace.py --set-tags=gfx,view,wm $cdandroid-sdk/platform-tools/systrace $pythonsystrace.py--set-tags=gfx,view,wm
$ adb shell stop $ adb shell start $adbshellstop $adbshellstart 你也可以通過(guò)手機(jī)上的圖形界面設(shè)置tags:
注意: 在圖形界面中設(shè)置tag時(shí)adb shell不用重新啟動(dòng),。 在配置完tags后,,你可以開(kāi)始收集操作信息了。 如何在當(dāng)前設(shè)置下啟動(dòng)trace:
你可以通過(guò) Systrace選項(xiàng) 來(lái)了解更多命令行選項(xiàng),。 分析trace報(bào)告在你獲取trace之后你可以在網(wǎng)頁(yè)瀏覽器中打開(kāi)它。這部分內(nèi)容告訴你怎么通過(guò)trace去分析和解決UI性能,。 監(jiān)視幀數(shù)每個(gè)應(yīng)用都有一行專門(mén)顯示frame,,每一幀就顯示為一個(gè)綠色的圓圈。不過(guò)也有例外,,當(dāng)顯示為黃色或者紅色的時(shí)候,,它的渲染時(shí)間超過(guò)了16.6ms(即達(dá)不到60fps的水準(zhǔn))?!痺’鍵可以放大,,看看這一幀的渲染過(guò)程中系統(tǒng)到底做了什么。 提示:你可以按右上角的’?’按鈕來(lái)查看界面使用幫助,。 圖2. Systrace顯示長(zhǎng)渲染時(shí)間的幀 單擊該幀可以高亮它,,這時(shí)候跟該幀有關(guān)的內(nèi)容會(huì)被突出顯示。在5.0及以上的系統(tǒng)中,顯示工作被拆分成UI線程和Render線程兩部分,;在5.0以下的系統(tǒng)中,,所有的顯示工作在UI線程中執(zhí)行。 點(diǎn)擊單個(gè)Frame下面的組件可以看他們所花費(fèi)的時(shí)間,。每個(gè)事件(比如 調(diào)查警告事件Systrace會(huì)自動(dòng)分析事件,它會(huì)將任何它認(rèn)為性能有問(wèn)題的東西都高亮警告,,并提示你要怎么去優(yōu)化,。 圖3. 選擇一個(gè)被高亮幀,,它會(huì)顯示出檢測(cè)到的問(wèn)題(回收ListView消耗時(shí)間太長(zhǎng)),。 在你選擇類似圖三中的問(wèn)題幀之后,它就會(huì)提示你檢測(cè)出的問(wèn)題,。在這個(gè)例子中,,它被警告的主要原因是ListView的回收和重新綁定花費(fèi)太多時(shí)間。在Systrace中也會(huì)提供一些對(duì)應(yīng)鏈接,,它們會(huì)提供更多解釋,。 如果你想知道UI線程怎么會(huì)花費(fèi)這么多時(shí)間的話,你可以使用 TraceView ,,它會(huì)告訴你都是哪些函數(shù)在消耗時(shí)間,。 你可以通過(guò)右側(cè)的’Alert’選項(xiàng)卡來(lái)查看整個(gè)trace過(guò)程中發(fā)生的所有問(wèn)題,并進(jìn)行快速定位,。 圖4. 點(diǎn)擊Alert選項(xiàng)卡,。 你可以將Alert面板中的問(wèn)題視為需要處理的bug,很有可能每一次微小的優(yōu)化能夠去除整個(gè)應(yīng)用中的警告,! 應(yīng)用級(jí)別調(diào)試 Systrace并不會(huì)追蹤應(yīng)用的所有工作,,所以你可以在有需求的情況下自己添加要追蹤的代碼部分。在Android 4.3及以上的代碼中,,你可以通過(guò) 下面這部分代碼展示了使用 public void ProcessPeople() { Trace.beginSection("ProcessPeople"); try { Trace.beginSection("Processing Jane"); try { // 待追蹤的代碼 } finally { Trace.endSection(); // 結(jié)束 "Processing Jane" } Trace.beginSection("Processing John"); try { // 待追蹤的代碼 } finally { Trace.endSection(); // 結(jié)束 "Processing John" } } finally { Trace.endSection(); // 結(jié)束 "ProcessPeople" } } publicvoidProcessPeople(){ Trace.beginSection("ProcessPeople"); try{ Trace.beginSection("Processing Jane"); try{ // 待追蹤的代碼 }finally{ Trace.endSection();// 結(jié)束 "Processing Jane" } Trace.beginSection("Processing John"); try{ // 待追蹤的代碼 }finally{ Trace.endSection();// 結(jié)束 "Processing John" } }finally{ Trace.endSection();// 結(jié)束 "ProcessPeople" } } 注意:在Trace是被嵌套在另一個(gè)Trace中的時(shí)候,, 注意:Trace的begin與end必須在同一線程之中執(zhí)行! 當(dāng)你使用應(yīng)用級(jí)別追蹤的時(shí)候,你必須通過(guò) 你在評(píng)估應(yīng)用的時(shí)候應(yīng)該開(kāi)啟應(yīng)用級(jí)別跟蹤,,即使當(dāng)你沒(méi)有手動(dòng)添加 |
|
來(lái)自: android之情殤 > 《待分類》