應用卡頓優化

概要

應用運行時的卡頓問題非常影響用戶體驗,嚴重降低產品表現力,本文將介紹應用卡頓原因以及分析方法等等。

卡頓問題可分為兩類,應用卡頓和系統卡頓,本文針對系統正常時應用卡頓場景。

黃油工程

Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,如果每次渲染都成功,這樣就能夠達到流暢的畫面所需要的60fps,為了能夠實現60fps,這意味著程序的大多數操作都必須在16ms內完成。

如上圖,第1幀在顯示時,GPU并沒有準備好第2幀數據,導致第1幀數據連續顯示兩次,導致不流暢、卡頓。應用需要減輕UI線程負擔,將耗時工作放入工作線程中,同時精簡繪制工作,保證16ms內可以完成一幀繪制。

圖層疊加

Android通過圖層疊加完成繪制。

左側的對象是生成圖形緩沖區的渲染器,如主屏幕、狀態欄和系統界面。SurfaceFlinger 是合成器,屏幕負責顯示合成界面。

應用界面層級應該盡量精簡,同時減少過度繪制問題,減輕系統壓力。

卡頓原因

應用卡頓常見的原因,UI線程負荷過重,繪制代碼不當等。系統卡頓或資源緊張也有可能導致應用卡頓,gc過多也能導致卡頓。此外,過度繪制,界面層級過多也會導致繪制效率下降。

在某些GPU性能較差的機器上,alpha動畫效率低下,也會導致卡頓。

分析方法

遇到卡頓問題,從現象入手,排除系統卡頓原因,接下來可通過log分析、工具定位解決卡頓問題。常用工具為traceview,systrace等。

Traceview,針對單一應用,統計具體一段時間內方法執行時間、次數等信息。

Systrace,記錄整機運行情況,包括cpu使用情況,vsync信號,gc信息等等,它也能記錄部分方法的執行情況,時間等。

Log分析,重點跟蹤gc情況,具體業務邏輯流程等。

Traceview

Traceview有兩種使用方式,既可使用DDMS采集數據,也可使用Debug類采集數據。使用DDMS采集數據的步驟如下:

  • 在應用的AndroidManifest.xml添加 android:debuggable="true",打開debug屬性
  • 打開DDMS面板,選中調試的應用
  • 點擊 Start Method Profiling 按鈕
  • 操作機器,執行對應需要性能分析的過程
  • 點擊 Stop Method Profiling 按鈕

抓取數據完成后會自動跳轉到traceview界面。

除了使用DDMS采集數據,也可以使用Debug類采集數據,使用Debug類采集數據步驟如下:

  • 在AndroidManifest.xml中添加寫sd卡權限
  • 在問題懷疑點處調用Debug.startMethodTracing("demo");
  • 在問題結束點處調用Debug.stopMethodTracing();,例如,可以在Activity的onCreate和onPause處分別調用上述方法。
  • 從sd卡中導致trace文件到pc端,利用ddms打開trace文件。

DDMS方式簡單,但很粗略。而使用Debug類采集數據,相對復雜,但更精確。

Traceview分析面板上,有很多的維度,一般來說,我們需要分析出那些耗時或者調用次數過多的函數,耗時的函數可通過維度Incl CPU Time分析。調用次數過多的函數可通過Cpu Time/Call維度分析。耗時的函數需要分析,很容易理解,但調用次數過多的函數很容易被忽略,如果view的onMeasure函數在不需要刷新時被調用多次,這也是值得關注的問題,所以需要分析函數的調用次數。

Traceview應用

模擬如下場景,ListView滑動卡頓,在getView方法中sleep一段時間,導致一幀數據無法在16ms內準備完成,因此滑動卡頓。

  public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        。。。。。。
        try {
            Thread.sleep(50);
        } catch (Exception e) {
        }
        return convertView;
    }

使用DDMS采集數據分析,按Incl CPU Time降序排列,traceview面板如下:

因為Incl CPU Time是包含內部調用的其它函數時間的,所以從上到下,花時間最多的就是虛擬機相關方法以及ActivityThread的main方法(應用線程啟動的入口方法)等。點擊每一個方法,均可以看到此方法自身花費時間、調用其它方法花費時間以及它的前一調用方法。一般來說通過跟蹤調用鏈,可找到對應問題所在。

從ActivityThread的main方法入手,parents屬性不用管,查看children屬性,self即是自身花費時間,此時為0,可見耗時是花在loop方法,一跟跟蹤調用鏈最終發現如下:

Adapter類的getView方法中調用了sleep方法以及setImageResource方法,而sleep方法耗時占用整體耗時的97%,如此,問題原兇已找到。

有一個小竅門,在分析某個方法的耗時構成時,如果此方法顯示有多個子方法耗時時,則選取耗時比較最大的子方法繼續分析,如下下面的情況:

我們預先已知listview滑動卡頓,那么耗時最多的應該是與listview相關的函數,而事實也是如此,繼續跟蹤線框內容,即可找到最終問題。

Systrace

Systrace與Traceview所不同的是,Systrace它能提供豐富得多的信息,它是對整機這段時間內的全面信息反饋,可以查看cpu分配情況,查看vsync信號,查看應用具體一幀圖像各階段耗時情況,甚至還可以查看gc情況,所以Systrace可以從系統高度,整體高度來查看卡頓問題。如果是分析單一應用卡頓問題,一定要通過Systrace來排除系統問題,確認這段時間內cpu資源足夠,也要查看gc情況。如果某段時間內,應用一幀卡頓,而cpu資源不夠或此時正在gc,則并不能說明是應用的問題。

由于google對android studio的大力推薦,現在使用eclipse抓取的Systrace,已經無法被chrome識別了,所以需要as抓取Systrace,抓取并打開Systrace的步驟如下:

  • 打開as,打開tools菜單,打開android device monitor
  • 點擊抓取systrace按鈕,勾選所需的信息,再確定
  • 在機器上進行相應操作,生成對應trace文件
  • 打開chrome瀏覽器,在地址欄上輸入chrome://tracing/,再使用chrome打開之前保存的trace文件

Systrace使用W放大,S縮小,A左移,D右移,右側有選擇條,可選擇鼠標點擊,也可選擇時間段標記。操作較為簡單,不再詳述。

Systrace有幾個需要注意的點,首先就是cpu的狀態問題。例如上圖紅框所示,obtainView方法上是無色的,而右邊小部分確是藍色或綠色,無色則代表cpu此時在睡眠狀態,藍色或綠色表示cpu處于運行狀態。如上圖所示,則可知此時cpu狀態異常,是否是調用了sleep方法導致這一幀卡頓了?可使用左鍵滑動選中一段距離,查看這段距離的cpu情況:

Systrace也是可以直接點擊紅色幀(紅色幀即是卡頓幀),查看紅色幀的一些基本情況,也能看到對于紅色幀的處理意見。

Systrace還能夠顯示當前的gc情況,例如:

Systrace還有一個強大的功能,選中查看某段時間內cpu的情況,如下圖所示,cpu這段時間內有gc操作,binder調用,還有打印log,如果gc操作過于頻繁,binder調用都是會影響系統性能的,另外log過多也是會影響系統性能的。

章節中的示例,抓取Systrace,分析,案例簡單,在Systrace上也一目了解,obtainView時間太長了,原因是cpu那段時間都處于sleep狀態。

性能優化的其它方法

前文介紹的是解決卡頓問題的重型武器,也有一些方法可以緩解卡頓或者讓性能更好。通過繪制原理的介紹,可以清楚地知道,如果UI的層級越少越好。怎么查看UI的層級呢?可以通過hierarchyviewer工具。可以通過自定義view形式實現UI層級的減少。UI層級減少,也會緩解過度繪制問題。

另外,減少界面刷新的次數也很重要,避免不必要的UI界面刷新。降低UI層級以及減少不必要刷新次數較為簡單,不再詳述。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容