應(yīng)用卡頓優(yōu)化

概要

應(yīng)用運(yùn)行時(shí)的卡頓問(wèn)題非常影響用戶體驗(yàn)荠列,嚴(yán)重降低產(chǎn)品表現(xiàn)力,本文將介紹應(yīng)用卡頓原因以及分析方法等等载城。

卡頓問(wèn)題可分為兩類肌似,應(yīng)用卡頓和系統(tǒng)卡頓,本文針對(duì)系統(tǒng)正常時(shí)應(yīng)用卡頓場(chǎng)景诉瓦。

黃油工程

Android系統(tǒng)每隔16ms發(fā)出VSYNC信號(hào)川队,觸發(fā)對(duì)UI進(jìn)行渲染,如果每次渲染都成功睬澡,這樣就能夠達(dá)到流暢的畫面所需要的60fps固额,為了能夠?qū)崿F(xiàn)60fps,這意味著程序的大多數(shù)操作都必須在16ms內(nèi)完成煞聪。

如上圖斗躏,第1幀在顯示時(shí),GPU并沒(méi)有準(zhǔn)備好第2幀數(shù)據(jù)昔脯,導(dǎo)致第1幀數(shù)據(jù)連續(xù)顯示兩次啄糙,導(dǎo)致不流暢笛臣、卡頓。應(yīng)用需要減輕UI線程負(fù)擔(dān)隧饼,將耗時(shí)工作放入工作線程中沈堡,同時(shí)精簡(jiǎn)繪制工作,保證16ms內(nèi)可以完成一幀繪制燕雁。

圖層疊加

Android通過(guò)圖層疊加完成繪制诞丽。

左側(cè)的對(duì)象是生成圖形緩沖區(qū)的渲染器,如主屏幕拐格、狀態(tài)欄和系統(tǒng)界面僧免。SurfaceFlinger 是合成器,屏幕負(fù)責(zé)顯示合成界面禁荒。

應(yīng)用界面層級(jí)應(yīng)該盡量精簡(jiǎn)猬膨,同時(shí)減少過(guò)度繪制問(wèn)題,減輕系統(tǒng)壓力呛伴。

卡頓原因

應(yīng)用卡頓常見(jiàn)的原因勃痴,UI線程負(fù)荷過(guò)重,繪制代碼不當(dāng)?shù)热瓤怠O到y(tǒng)卡頓或資源緊張也有可能導(dǎo)致應(yīng)用卡頓沛申,gc過(guò)多也能導(dǎo)致卡頓。此外姐军,過(guò)度繪制铁材,界面層級(jí)過(guò)多也會(huì)導(dǎo)致繪制效率下降。

在某些GPU性能較差的機(jī)器上奕锌,alpha動(dòng)畫效率低下著觉,也會(huì)導(dǎo)致卡頓。

分析方法

遇到卡頓問(wèn)題惊暴,從現(xiàn)象入手饼丘,排除系統(tǒng)卡頓原因,接下來(lái)可通過(guò)log分析辽话、工具定位解決卡頓問(wèn)題肄鸽。常用工具為traceview,systrace等油啤。

Traceview典徘,針對(duì)單一應(yīng)用,統(tǒng)計(jì)具體一段時(shí)間內(nèi)方法執(zhí)行時(shí)間益咬、次數(shù)等信息逮诲。

Systrace,記錄整機(jī)運(yùn)行情況,包括cpu使用情況汛骂,vsync信號(hào)罕模,gc信息等等,它也能記錄部分方法的執(zhí)行情況帘瞭,時(shí)間等淑掌。

Log分析,重點(diǎn)跟蹤gc情況蝶念,具體業(yè)務(wù)邏輯流程等抛腕。

Traceview

Traceview有兩種使用方式,既可使用DDMS采集數(shù)據(jù)媒殉,也可使用Debug類采集數(shù)據(jù)担敌。使用DDMS采集數(shù)據(jù)的步驟如下:

  • 在應(yīng)用的AndroidManifest.xml添加 android:debuggable="true",打開(kāi)debug屬性
  • 打開(kāi)DDMS面板廷蓉,選中調(diào)試的應(yīng)用
  • 點(diǎn)擊 Start Method Profiling 按鈕
  • 操作機(jī)器全封,執(zhí)行對(duì)應(yīng)需要性能分析的過(guò)程
  • 點(diǎn)擊 Stop Method Profiling 按鈕

抓取數(shù)據(jù)完成后會(huì)自動(dòng)跳轉(zhuǎn)到traceview界面。

除了使用DDMS采集數(shù)據(jù)桃犬,也可以使用Debug類采集數(shù)據(jù)刹悴,使用Debug類采集數(shù)據(jù)步驟如下:

  • 在AndroidManifest.xml中添加寫sd卡權(quán)限
  • 在問(wèn)題懷疑點(diǎn)處調(diào)用Debug.startMethodTracing("demo");
  • 在問(wèn)題結(jié)束點(diǎn)處調(diào)用Debug.stopMethodTracing();,例如攒暇,可以在Activity的onCreate和onPause處分別調(diào)用上述方法土匀。
  • 從sd卡中導(dǎo)致trace文件到pc端,利用ddms打開(kāi)trace文件形用。

DDMS方式簡(jiǎn)單就轧,但很粗略。而使用Debug類采集數(shù)據(jù)田度,相對(duì)復(fù)雜妒御,但更精確。

Traceview分析面板上镇饺,有很多的維度携丁,一般來(lái)說(shuō),我們需要分析出那些耗時(shí)或者調(diào)用次數(shù)過(guò)多的函數(shù)兰怠,耗時(shí)的函數(shù)可通過(guò)維度Incl CPU Time分析。調(diào)用次數(shù)過(guò)多的函數(shù)可通過(guò)Cpu Time/Call維度分析李茫。耗時(shí)的函數(shù)需要分析揭保,很容易理解,但調(diào)用次數(shù)過(guò)多的函數(shù)很容易被忽略魄宏,如果view的onMeasure函數(shù)在不需要刷新時(shí)被調(diào)用多次秸侣,這也是值得關(guān)注的問(wèn)題,所以需要分析函數(shù)的調(diào)用次數(shù)。

Traceview應(yīng)用

模擬如下場(chǎng)景味榛,ListView滑動(dòng)卡頓椭坚,在getView方法中sleep一段時(shí)間,導(dǎo)致一幀數(shù)據(jù)無(wú)法在16ms內(nèi)準(zhǔn)備完成搏色,因此滑動(dòng)卡頓善茎。

  public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        。频轿。垂涯。。航邢。耕赘。
        try {
            Thread.sleep(50);
        } catch (Exception e) {
        }
        return convertView;
    }

使用DDMS采集數(shù)據(jù)分析,按Incl CPU Time降序排列膳殷,traceview面板如下:

因?yàn)镮ncl CPU Time是包含內(nèi)部調(diào)用的其它函數(shù)時(shí)間的操骡,所以從上到下,花時(shí)間最多的就是虛擬機(jī)相關(guān)方法以及ActivityThread的main方法(應(yīng)用線程啟動(dòng)的入口方法)等赚窃。點(diǎn)擊每一個(gè)方法册招,均可以看到此方法自身花費(fèi)時(shí)間、調(diào)用其它方法花費(fèi)時(shí)間以及它的前一調(diào)用方法考榨。一般來(lái)說(shuō)通過(guò)跟蹤調(diào)用鏈跨细,可找到對(duì)應(yīng)問(wèn)題所在。

從ActivityThread的main方法入手河质,parents屬性不用管冀惭,查看children屬性,self即是自身花費(fèi)時(shí)間掀鹅,此時(shí)為0散休,可見(jiàn)耗時(shí)是花在loop方法,一跟跟蹤調(diào)用鏈最終發(fā)現(xiàn)如下:

Adapter類的getView方法中調(diào)用了sleep方法以及setImageResource方法乐尊,而sleep方法耗時(shí)占用整體耗時(shí)的97%戚丸,如此,問(wèn)題原兇已找到扔嵌。

有一個(gè)小竅門限府,在分析某個(gè)方法的耗時(shí)構(gòu)成時(shí),如果此方法顯示有多個(gè)子方法耗時(shí)時(shí)痢缎,則選取耗時(shí)比較最大的子方法繼續(xù)分析胁勺,如下下面的情況:

我們預(yù)先已知listview滑動(dòng)卡頓,那么耗時(shí)最多的應(yīng)該是與listview相關(guān)的函數(shù)独旷,而事實(shí)也是如此署穗,繼續(xù)跟蹤線框內(nèi)容寥裂,即可找到最終問(wèn)題。

Systrace

Systrace與Traceview所不同的是案疲,Systrace它能提供豐富得多的信息封恰,它是對(duì)整機(jī)這段時(shí)間內(nèi)的全面信息反饋,可以查看cpu分配情況褐啡,查看vsync信號(hào)诺舔,查看應(yīng)用具體一幀圖像各階段耗時(shí)情況,甚至還可以查看gc情況春贸,所以Systrace可以從系統(tǒng)高度混萝,整體高度來(lái)查看卡頓問(wèn)題。如果是分析單一應(yīng)用卡頓問(wèn)題萍恕,一定要通過(guò)Systrace來(lái)排除系統(tǒng)問(wèn)題逸嘀,確認(rèn)這段時(shí)間內(nèi)cpu資源足夠,也要查看gc情況允粤。如果某段時(shí)間內(nèi)崭倘,應(yīng)用一幀卡頓,而cpu資源不夠或此時(shí)正在gc类垫,則并不能說(shuō)明是應(yīng)用的問(wèn)題司光。

由于google對(duì)android studio的大力推薦,現(xiàn)在使用eclipse抓取的Systrace悉患,已經(jīng)無(wú)法被chrome識(shí)別了残家,所以需要as抓取Systrace,抓取并打開(kāi)Systrace的步驟如下:

  • 打開(kāi)as售躁,打開(kāi)tools菜單坞淮,打開(kāi)android device monitor
  • 點(diǎn)擊抓取systrace按鈕,勾選所需的信息陪捷,再確定
  • 在機(jī)器上進(jìn)行相應(yīng)操作回窘,生成對(duì)應(yīng)trace文件
  • 打開(kāi)chrome瀏覽器,在地址欄上輸入chrome://tracing/市袖,再使用chrome打開(kāi)之前保存的trace文件

Systrace使用W放大啡直,S縮小,A左移苍碟,D右移酒觅,右側(cè)有選擇條,可選擇鼠標(biāo)點(diǎn)擊微峰,也可選擇時(shí)間段標(biāo)記阐滩。操作較為簡(jiǎn)單,不再詳述县忌。

Systrace有幾個(gè)需要注意的點(diǎn)掂榔,首先就是cpu的狀態(tài)問(wèn)題。例如上圖紅框所示症杏,obtainView方法上是無(wú)色的装获,而右邊小部分確是藍(lán)色或綠色,無(wú)色則代表cpu此時(shí)在睡眠狀態(tài)厉颤,藍(lán)色或綠色表示cpu處于運(yùn)行狀態(tài)穴豫。如上圖所示,則可知此時(shí)cpu狀態(tài)異常逼友,是否是調(diào)用了sleep方法導(dǎo)致這一幀卡頓了精肃?可使用左鍵滑動(dòng)選中一段距離,查看這段距離的cpu情況:

Systrace也是可以直接點(diǎn)擊紅色幀(紅色幀即是卡頓幀)帜乞,查看紅色幀的一些基本情況司抱,也能看到對(duì)于紅色幀的處理意見(jiàn)。

Systrace還能夠顯示當(dāng)前的gc情況黎烈,例如:

Systrace還有一個(gè)強(qiáng)大的功能习柠,選中查看某段時(shí)間內(nèi)cpu的情況,如下圖所示照棋,cpu這段時(shí)間內(nèi)有g(shù)c操作资溃,binder調(diào)用,還有打印log烈炭,如果gc操作過(guò)于頻繁溶锭,binder調(diào)用都是會(huì)影響系統(tǒng)性能的,另外log過(guò)多也是會(huì)影響系統(tǒng)性能的符隙。

章節(jié)中的示例趴捅,抓取Systrace,分析膏执,案例簡(jiǎn)單驻售,在Systrace上也一目了解,obtainView時(shí)間太長(zhǎng)了更米,原因是cpu那段時(shí)間都處于sleep狀態(tài)欺栗。

性能優(yōu)化的其它方法

前文介紹的是解決卡頓問(wèn)題的重型武器,也有一些方法可以緩解卡頓或者讓性能更好征峦。通過(guò)繪制原理的介紹迟几,可以清楚地知道,如果UI的層級(jí)越少越好栏笆。怎么查看UI的層級(jí)呢类腮?可以通過(guò)hierarchyviewer工具◎燃樱可以通過(guò)自定義view形式實(shí)現(xiàn)UI層級(jí)的減少蚜枢。UI層級(jí)減少缸逃,也會(huì)緩解過(guò)度繪制問(wèn)題。

另外厂抽,減少界面刷新的次數(shù)也很重要需频,避免不必要的UI界面刷新。降低UI層級(jí)以及減少不必要刷新次數(shù)較為簡(jiǎn)單筷凤,不再詳述昭殉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市藐守,隨后出現(xiàn)的幾起案子挪丢,更是在濱河造成了極大的恐慌,老刑警劉巖卢厂,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乾蓬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡足淆,警方通過(guò)查閱死者的電腦和手機(jī)巢块,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巧号,“玉大人族奢,你說(shuō)我怎么就攤上這事〉ず瑁” “怎么了越走?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)靠欢。 經(jīng)常有香客問(wèn)我廊敌,道長(zhǎng),這世上最難降的妖魔是什么门怪? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任骡澈,我火速辦了婚禮,結(jié)果婚禮上掷空,老公的妹妹穿的比我還像新娘肋殴。我一直安慰自己,他們只是感情好坦弟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布护锤。 她就那樣靜靜地躺著,像睡著了一般酿傍。 火紅的嫁衣襯著肌膚如雪烙懦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天赤炒,我揣著相機(jī)與錄音氯析,去河邊找鬼亏较。 笑死,一個(gè)胖子當(dāng)著我的面吹牛魄鸦,可吹牛的內(nèi)容都是我干的宴杀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拾因,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了旷余?” 一聲冷哼從身側(cè)響起绢记,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎正卧,沒(méi)想到半個(gè)月后蠢熄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炉旷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年签孔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窘行。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饥追,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罐盔,到底是詐尸還是另有隱情但绕,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布惶看,位于F島的核電站捏顺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纬黎。R本人自食惡果不足惜幅骄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望本今。 院中可真熱鬧拆座,春花似錦、人聲如沸诈泼。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铐达。三九已至岖赋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓮孙,已是汗流浹背唐断。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工选脊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脸甘。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓恳啥,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親丹诀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钝的,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容