Android中app卡顿原因分析示例
http://www.cnblogs.com/zhucai/p/weibo-graphics-performance-analyse.html
朱才
專注于Android圖形動畫 MIUI工程師
隨筆- 21?文章- 0?評論- 164?Android中app卡頓原因分析示例
在知乎回答了一個“為什么微博的app在iPhone比Android上流暢”的問題。后面部分是一個典型的動畫卡頓的性能分析過程,因此帖在這里。有編程問題可以在這里交流。知乎鏈接。
=========================================================
我來說下我所知道的事情。我不知道iOS為什么流暢,但我知道一些Android為什么不流暢的原因。
首先,就題主所說的問題,我用iPad和小米Pad對比了一下微博滑動滾屏這件事情(2014年8月10日目前微博app最新版本)。正如題主所說,直觀感受上明顯感覺iOS要流暢、舒服。
在這件事情上我認為主要是這三個原因:
當你滑動界面然后松手,這時界面會繼續滑動,然后速度減小,直到速度為0時停止。iOS下速度減小的這個過程比較慢,尤其是快要停的時候是慢慢停的,視覺上有種很順滑的感覺;Android下則從松手到停要快很多,相比之下有種戛然而止的感覺。
從數據/技術角度來看這個事情,我們滑動界面的最終目的不是為了“動”,而是為了“?!?#xff0c;因此只要平滑的到達目的地,似乎越快完成這個過程越好,所以Android的選擇是理所當然的。但事實是,大家普遍更喜歡iOS的方式,這樣做顯得更順滑、更優雅。
絕大部分時間兩者都能保持60FPS左右的滿幀率。但都會有偶爾的掉幀。并且Android上要比iOS上嚴重很多。(好吧,比起前兩年,已經好太多了。)我前前后后滑動了幾十次,iOS在前面遇到1次掉幀,后面就很穩定了。而Android幾乎每滑動一次都會伴隨一次掉幀。這完全就是真真實實的卡頓,用戶必然會感覺到那一刻的不流暢。Android掉幀的原因我后面再詳細分析。
從手指碰到觸摸屏,到屏幕上顯示處理這次觸摸產生的畫面,是需要時間的。時間越短感覺越跟手。據說iOS的觸摸屏的處理時間要比一般的Android手機快,這不是我的專長,不知道怎么驗證。但在軟件系統層面,Android的顯示機制是app-->SurfaceFlinger-->Display,這比傳統的app-->Display多了一步,主要基于這個原因,畫面最終輸出到屏幕要比傳統的方式慢一幀(16.7ms)。
我覺得第1點造成的影響最大,恰恰卻是最技術/設備無關的。如果微博app或者Android系統要改變,很容易就可以調得跟iOS一模一樣。但正是由于這是產品形態上的差別而不是純粹技術上的優劣,反倒成了Android最不太可能改變的。
第2點的影響其次,當然是指在目前這個大部分時候都能滿幀的情況下。這方面是Android從早期到現在進步最明顯的方面,使用了很多方法來優化幀率。但就算現在Android進化了很多,硬件性能也進化了很多,卻仍舊不可能徹底消滅掉幀的情況。
第3點通俗的講就是跟手性,跟手性的重要性不言而喻,但現在的差別比較細微,且具體數據我也不清楚。
我想過一個辦法讓桌面、微博這種內容和手一起動的應用繪制到屏幕的速度快一幀(16.7ms),其實就是抵消之前提到的慢的那一幀,需要framework層和app層一起配合改動,目前已申請了專利但代碼還沒進,將來有時間了應該會進到MIUI。感興趣的可以看看專利:滑動操作響應方法、裝置及終端設備。
最后我來用專業技術分析一下微博app在Android里掉幀的原因。非編程人員可以不看下去了。(這個過程我使用的是小米3高通版+最新版微博app。)
最初,我認為這種現象很像GC(垃圾回收)導致的,于是打開logcat觀察每次卡頓的時候有沒有GC發生。結果發現并沒有。停下來的時候才會有GC,這說明微博app在滑動過程中控制得不錯,在停下來的一刻才去分配內存,使GC不影響幀率。
然后我打開“開發者選項”->“GPU呈現模式分析”->“在屏幕上顯示為條形圖”(好像是4.4才有這個選項,之前的只能在dumpsys里看),這會在屏幕上直觀的顯示每幀繪制花費的時間。屏幕上有條基準線大概是16ms,如果超過這條線則很有可能掉幀了。如果下面的藍色部分很長則說明是軟件draw的部分太費時,那么可以通過traceview來繼續分析draw的java代碼。(我假定了現在的app都是硬件加速的方式。)如果中間紅色部分很長則說明是OpenGL ES繪制過程太費時。可以用gltrace來分析OpenGL ES的調用過程。
打開選項后使用微博app,發現雖然偶爾有超基準線,但并不嚴重,并且卡頓的時候并沒有明顯異常。
于是我開始使用systrace,這下就很明顯了:
可以發現每隔幾幀,就會有一次大間隙,圖中我圈了紅圈圈的兩個地方都明顯超過正常的耗時時間。現在問題是,這些地方的代碼在干什么呢?是什么花費了這么長時間?
放大后發現都是這兩個:obtainView和setupListItem。它們都是在draw之前調用的,這也解釋了通過上一步的方法(“GPU呈現模式分析”)為什么沒有顯示出來,因為那個方法只展示draw里面的時間消耗。
通過在源碼里搜索obtainView和setupListItem,可以發現是AbsListView的obtainView方法和ListView的setupChild方法打下的這個log。
接下來,我們用traceview來看看這兩個方法里面究竟調用了什么代碼導致耗時過長。
跟蹤obtainView最終到了這里:
代碼混淆了,看不太出來了,也懶得再跟下去了。但隨便點了點然后看到:
TextView.setText用了挺多的時間。感覺Android團隊應該優化優化這個方法。
然后再來跟蹤setupChild方法:
都是measure占用的時間,并且調用次數比較多。這應該說明了View的數量不少。用hierarchyviewer看了下,的確不少,一條微博有50多個View:
結論:我們最終大致找到了耗時的代碼及部分原因。這兩個耗時方法應該都是有可能減下來的,但應該不那么容易。
在Android上實現功能比較容易,但如果默認實現有了性能問題,要想解決就不好說了,有時候要繞很遠。
最后,列一些相關鏈接:
Android圖形架構(繪圖慢一幀的事情這里有說):http://source.android.com/devices/graphics/architecture.html
Android Performance Case Study:http://www.curious-creature.org/docs/android-performance-case-study-1.html
轉載需注明出處:http://cnblogs.com/zhucai/
我的微博:http://weibo.com/zhucai
標簽: android, graphics, performance 綠色通道: 好文要頂 關注我 收藏該文 與我聯系 朱才關注 - 1
粉絲 - 18 榮譽: 推薦博客 +加關注 0 0 (請您對文章做出評價) ? 上一篇: 二維坐標圖
? 下一篇: MIUI 6的毛玻璃效果的技術實現(實時模糊)
posted @ 2014-08-10 17:38 朱才 閱讀( 7529) 評論( 2) 編輯 收藏
發表評論 回復引用 #1樓 2015-02-13 10:17 | Elta 昨天看到了你的這篇博文,想和你說一下我在使用應用的時候發現的一個卡頓現象。
軟件:Adobe reader
具體現象:在看PDF文件時,食指按住屏幕上下滑動,一開始的時候很流暢,在不松開手指的情況下反復上下滑動,開始出現卡頓現在。用手機帶的條形圖沒有發現有掉幀。不會再向下分析了,很好奇這是什么原因導致的,是否有辦法規避這個問題呢? 支持(0) 反對(0)
回復引用 #2樓 [ 樓主] 2015-03-03 08:51 | 朱才 @Elta
那可以估計出是繪圖之間的時間導致的??梢杂胹ystrace來繼續分析。 支持(0) 反對(0)
刷新評論 刷新頁面 返回頂部 發表評論
昵稱:
評論內容:注銷 訂閱評論
[使用Ctrl+Enter鍵快速提交]
【推薦】50萬行VC++源碼: 大型組態工控、電力仿真CAD與GIS源碼庫【熱門】支持Visual Studio2015的葡萄城控件新品發布暨夏季促銷
最新IT新聞:
· 禁令解除:國內主機游戲就能復活?
· 高通取得無線充電技術新突破:支持金屬機身手機
· Twitter盤后大跌12% 臨時CEO言論嚇壞投資者
· 在線超新星搜尋項目啟動 在家就能搞科研
· 希臘前財政部長承認授權侵入國家稅收數據庫
? 更多新聞... 最新知識庫文章:
· 通過心理學知識提高問題定位與解決能力(上)
· 用醫生的思考方式調試你的代碼
· 代碼審查的價值——為何做、何時做、如何做?
· 所有程序員都應該遵守的11條規則
· RESTful架構詳解
? 更多知識庫文章... 昵稱: 朱才
園齡: 6年3個月
榮譽: 推薦博客
粉絲: 18
關注: 1 +加關注
| |||||||||
| 28 | 29 | 30 | 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | |||
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | |||
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | |||
| 26 | 27 | 28 | 29 | 30 | 31 | 1 | |||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | |||
搜索
?常用鏈接
- 我的隨筆
- 我的評論
- 我的參與
- 最新評論
- 我的標簽
- 更多鏈接
我的標簽
- android(4)
- canvas(3)
- graphics(3)
- html5(2)
- LambdaParser(2)
- delegate(2)
- js(2)
- json(1)
- Lambda(1)
- DataContractJsonSerializer(1)
- 更多
隨筆檔案
- 2015年7月 (1)
- 2014年12月 (2)
- 2014年8月 (1)
- 2011年10月 (1)
- 2011年2月 (1)
- 2010年8月 (1)
- 2010年7月 (2)
- 2010年6月 (1)
- 2010年5月 (2)
- 2010年1月 (1)
- 2009年12月 (1)
- 2009年10月 (2)
- 2009年7月 (1)
- 2009年6月 (1)
- 2009年5月 (3)
鏈接
- 我的微博
最新評論
- 1. Re:Android中app卡頓原因分析示例
- @Elta那可以估計出是繪圖之間的時間導致的??梢杂胹ystrace來繼續分析。...
- --朱才
- 2. Re:Android中app卡頓原因分析示例
- 昨天看到了你的這篇博文,想和你說一下我在使用應用的時候發現的一個卡頓現象。軟件:Adobe reader具體現象:在看PDF文件時,食指按住屏幕上下滑動,一開始的時候很流暢,在不松開手指的情況下反復上......
- --Elta
- 3. Re:MIUI 6的毛玻璃效果的技術實現(實時模糊)
- framework層?
- --專注-
- 4. Re:動態計算表達式
- 好厲害 舉一反三哇
- --z5337
閱讀排行榜
- 1. C#與Java的比較(17406)
- 2. Android中app卡頓原因分析示例(7529)
- 3. 用HashSet代替List(6034)
- 4. js中用gb2312編碼解碼(4858)
- 5. 我開發的幾個chrome擴展(3901)
評論排行榜
- 1. 我開發的幾個chrome擴展(38)
- 2. C#與Java的比較(17)
- 3. 用HashSet代替List(16)
- 4. out參數的失控(13)
- 5. LambdaParser:解析代碼字符串為Lambda表達式并編譯為委托(13)
推薦排行榜
- 1. 乒乓球的運動模擬(7)
- 2. LambdaParser的實現(4)
- 3. C#與Java的比較(4)
- 4. 我開發的幾個chrome擴展(3)
- 5. 動態計算表達式(3)
總結
以上是生活随笔為你收集整理的Android中app卡顿原因分析示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 几句禅语的解释
- 下一篇: 深入探索Android内存优化