Android開發——利用Systrace工具優化Android App的運行性能

原文地址:http://www.mobile-open.com/2015/85005.html


本文主要講述瞭如何利用Systrace工具優化你的Android App,瞭解你的APP各個子系統的運行狀況,從本質上提升移動應用的運行速度。現在把Systrace的使用整理出來分享給Android程序員兄弟們,希望給他們的開發工作帶來幫助。本文也是Systrace的使用教程,通過認真的閱讀本教程,能夠掌握Systrace的基本用法。

###信條

  • 用數據說話:在細微的差別面前大部分人無法感知辨別,在每一次優化代碼後使用如下將介紹的工具進行檢驗。
  • 使用低性能機器測試:低性能的機器會更多地暴露問題。
  • 意識到等價交換的思想:所有優良代碼之上的優化都是基於等價交換,而這其中基本上都是以空間換時間。

###Systrace

Systrace是大多數開發者不去使用的工具,因爲大家不知道如何使用它提供的數據。Systrace 的功能包括跟蹤系統的 I/O 操作、內核工作隊列、CPU 負載以及 Android 各個子系統的運行狀況等。

它有三部分組成:

  • 內核部分:Systrace 利用了Linux Kernel 中的 ftrace 功能。所以,如果要使用 Systrace 的話,必須開啓 kernel 中和 ftrace 相關的模塊。
  • 數據採集部分:Android 定義了一個 Trace 類。應用程序可利用該類把統計信息輸出給 ftrace。同時,Android 還有一個 atrace 程序,它可以從 ftrace 中讀取統計信息然後交給數據分析工具來處理。
  • 數據分析工具:Android 提供一個 systrace.py(python腳本文件,位於Android SDK 目錄 /tools/systrace 中,其內部將調用 atrace 程序)用來配置數據採集的方式(如採集數據的標籤、輸出文件名等)和收集 ftrace 統計數據並生成一個結果網頁文件供用戶查看。

Systrace使用方式 有兩種:

  • 1.Device Monitor
  • 2.命令行
    $ cd android-sdk/platform-tools/systrace $ python systrace.py --set-tags=gfx,view,wm $ adb shell stop $ adb shell start

ps:先在設備中打開Settings > Developer options > Monitoring > Enable traces。

抓取的信息使用瀏覽器打開如下:

讓你的App飛起來

我們來選取一個Alert來看一下:

讓你的App飛起來

可以看到Alert原因是Long View#draw(),下面還會有相關文檔鏈接。選擇Frame這一行,就能看到每一幀的渲染,通過不同的顏色發現一些問題,我們來選擇紅色的一幀:

讓你的App飛起來

在底部,有三個Alert信息,打開“Inflation during ListView recycling”:

讓你的App飛起來

看這部分耗費的時間,32ms,超過了保證60fps的16ms。再看下面細分每一步耗費的時間,有5個obtainView都消耗了大約 5ms。Description指出了問題所在,沒有使用ListView的複用機製造成inflate單個Item成本過高。再看上面的圖形部分,它將 所有的東西都可視化,我們放大來看“inflate”:

讓你的App飛起來

在選擇一幀之後,可以通過“m”鍵顯示具體耗費的時間。可以看到耗費超過19ms渲染這一幀。展開這一幀唯一的一個Alert,看到“Scheduling delay”。選擇最長的DrawFrame來看一下:

讓你的App飛起來

Wall duration是從時間片的開始到結束。CPU Duration是CPU的實際運行時間。注意這兩個時間的巨大差別,來看一下CPU這段時間做了什麼:

讓你的App飛起來

四個核心都處於忙碌狀態,選擇一個Thread看它從哪裏發起,一個包名爲com.udinic.keepbusyapp。原來是其它app的原 因。這種情況通常是暫時的,因爲其它app不太可能在後臺長時間佔用CPU,這些線程可能來自你的App的其它進程,或者是主進程。由於Systrace 是以系統的角度返回一些信息,要進一步獲取CPU滿負荷運行的原因,我們來使用另一個工具Traceview。

###TraceviewTraceview是一個很好的性能分析工具。它可以通過圖形化的方式讓我們瞭解我們要跟蹤的程序的性能,並且能具體到method:

讓你的App飛起來

使用方式同樣有兩種,Android Device Monitor或者使用代碼,參考 這裏 .

我們來看一下不同列代表的含義:

  • Name:method的名稱,前面有一個和上圖對應的顏色標識。
  • Inclusive CPU Time:此方法和子方法調用佔用的CPU時間。
  • Exclusive CPU Time:此方法單獨調用佔用的CPU時間。
  • Inclusive / Exclusive Real Time:從方法開始到結束的時間,類似於“Wall Duration“。
  • Calls+Recursion:調用次數。
  • CPU/Real time per Call:每次調用平均佔用的CPU時間。

我打開了一個不能平滑滾動的App,開始跟蹤,滾動以下部分,停止跟蹤。找到getView()方法,展開:

讓你的App飛起來

這個方法調用了12次,每次CPU時間3ms,但是每次調用的真實時間是162ms,絕對有問題!

查看這個方法下地Children,Thread.join()耗費了約98%的inclusive real time。這個方法是用來等待其他線程結束。另一個children是Thread.start(),由此認定getView()方法啓動了一個線程並等 待它結束。

但是這個線程在哪?

我們不知道這個getView()中的線程做了什麼,因爲getView()中沒有直接啓動它。爲了找到它,我查找了Thread.start()方法。最終發現了它:

讓你的App飛起來

本文到此結束,需要的朋友可以參考下。希望通過本文能讓兄弟們開發的Android應用運行速度達到質的提升。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章