Android系統性能調優工具介紹

Android系統性能調優工具介紹

在軟件開發過程中,想必很多讀者都遇到過系統性能問題。而解決系統性能問題的幾個主要步驟是:

  • 測評:對系統進行大量有針對性的測試,以得到合適的測試數據。
  • 分析系統瓶頸:分析測試數據,找到其中的hotspot(熱點,即bottleneck)。
  • 性能優化:對hotspot相關的代碼進行優化。

由上述步驟可知,性能優化的目標對象是hotspot。如果找到的hotspot並非真正的熱點,則性能優化的結果必然是事倍功半甚至竹籃打水一場空。所以,作爲Android性能調優相關知識的第一部分,本篇首先將向讀者介紹Android平臺中三個重要的性能測試工具,它們能很好得幫助開發者找到hotspot

Traceview介紹

1.1  Traceview簡介

TraceviewAndroid平臺特有的數據採集和分析工具,它主要用於分析Android中應用程序的hotspotTraceview本身只是一個數據分析工具,而數據的採集則需要使用Android SDK中的Debug類或者利用DDMS工具。二者的用法如下:

  • 開發者在一些關鍵代碼段開始前調用Android SDK中Debug類的startMethodTracing函數,並在關鍵代碼段結束前調用stopMethodTracing函數。這兩個函數運行過 程中將採集運行時間內該應用所有線程(注意,只能是Java線程)的函數執行情況,並將採集數據保存到/mnt/sdcard/下的一個文件中。開發者然 後需要利用SDK中的Traceview工具來分析這些數據。
  • 藉助Android SDK中的DDMS工具。DDMS可採集系統中某個正在運行的進程的函數調用信息。對開發者而言,此方法適用於沒有目標應用源代碼的情況。DDMS工具中Traceview的使用如圖1-1所示。

Android系統性能調優工具介紹

1-1  DDMSTraceview使用示意圖

點擊圖1-1中所示按鈕即可以採集目標進程的數據。當停止採集時,DDMS會自動觸發Traceview工具來瀏覽採集數據。

下面,我們通過一個示例程序向讀者介紹Debug類以及Traceview的使用。

1.2  Traceview示例分析

示例程序運行時的界面如圖1-2所示:

Android系統性能調優工具介紹

1-2  示例界面圖

1-2中:

  • SystraceDemoStringAAA等字樣是TraceviewDemo程序啓動時ListView最初顯示的字符串。
  • 當用戶點擊ListView中的某一項時,Traceview將計算對應項當前顯示的字符串的MD5值40次,然後用計算得到的MD5字符串替換該項之前顯示的內容。其效果如圖1-2中的“MD5值“箭頭所示。

該示例的關鍵代碼如圖1-3所示:

Android系統性能調優工具介紹

1-3示例代碼

由圖1-3可知:

  • 左圖中,Debug類的startMethodTracing和stopMethodTracing分別在MainAcvtivity的構造方法和onDestroy函數中調用。
  • onCreate函數中我們設置了第一個hotspot,即getStringToShow函數。它將解析一個XML文件,並將解析後的字符串保存到mListItem中以作爲ListView的顯示內容。
  • 右圖中,當用戶點擊ListView中的某個Item時,程序在onListItem中將計算MD5值40次,然後用計算結果做爲被點擊項的新字符串顯示。generateMD5中的函數是本示例的第二個hotspot。

現在,我們用Traceview工具將測試結果文件TraceviewDemo.trace打開。

Traceview界面比較複雜,其UI劃分爲上下兩個面板,即Timeline Panel(時間線面板)Profile Panel(分析面板)。圖1-4所示爲Timeline Panel界面:

Android系統性能調優工具介紹

1-4  Traceview Timeline Panel示意圖

1-4中的Timeline Panel又可細分爲左右兩個Pane

  • 左邊Pane顯示的是測試數據中所採集的線程信息。由圖1-4可知,本次測試數據採集了main線程,兩個Binder線程和其它系統輔助線程(例如GC線程等)的信息。
  • 右邊Pane所示爲時間線,時間線上是每個線程測試時間段內所涉及的函數調用信息。這些信息包括函數名、函數執行時間等。由圖1-4可知,main線程對應行的的內容非常豐富,而其他線程在這段時間內幹得工作則要少得多。
  • 另外,開發者可以在時間線Pane中移動時間線縱軸。縱軸上邊將顯示當前時間點中某線程正在執行的函數信息。

現在來看TraceviewProfile Panel界面,如圖1-5所示:

Android系統性能調優工具介紹

1-5  TraceviewProfile Panel界面

Profile PanelTraceview的核心界面,其內涵非常豐富。它主要展示了某個線程(先在Timeline Panel中選擇線程)中各個函數調用的情況,包括CPU使用時間、調用次數等信息。而這些信息正是查找hotspot的關鍵依據。所以,對開發者而言,一定要了解Profile Panel中各列的含義。筆者總結了其中幾個重要列的作用,如表1-1所示:

1-1  Profile Panel各列作用說明

列名

描述

Name

該線程運行過程中所調用的函數名

Incl Cpu Time

某函數佔用的CPU時間,包含內部調用其它函數的CPU時間

Excl Cpu Time

某函數佔用的CPU時間,但不含內部調用其它函數所佔用的CPU時間

Incl Real Time

某函數運行的真實時間(以毫秒爲單位),內含調用其它函數所佔用的真實時間

Excl Real Time

某函數運行的真實時間(以毫秒爲單位),不含調用其它函數所佔用的真實時間

Call+Recur Calls/Total

某函數被調用次數以及遞歸調用佔總調用次數的百分比

Cpu Time/Call

某函數調用CPU時間與調用次數的比。相當於該函數平均執行時間

Real Time/Call

CPU Time/Call類似,只不過統計單位換成了真實時間

另外,每一個Time列還對應有一個用時間百分比來統計的列(如Incl Cpu Time列對應還有一個列名爲Incl Cpu Time %的列,表示以時間百分比來統計的Incl Cpu Time)。

瞭解完TraceviewUI後,現在介紹如何利用Traceview來查找hotspot

一般而言,hotspot包括兩種類型的函數:

  • 一類是調用次數不多,但每次調用卻需要花費很長時間的函數。在示例代碼中,它就是hotspot 1。
  • 一類是那些自身佔用時間不長,但調用卻非常頻繁的函數。在示例代碼中,它就是hotspot 2。

首先,我們來查找hotspot 1

Profile Panel中,選擇按Cpu Time/Call進行降序排序(從上之下排列,每項的耗費時間由高到低),得到如圖1-6所示的結果:

Android系統性能調優工具介紹

1-6  CPU Time/Call降序排列數據

1-6中:

  • MainActivity.onCreate是應用程序中的函數,它耗時爲4618.684。然後,點擊MainActivity.onCreate項,得到箭頭所示的小圖。
  • 小圖中,Parents一行顯示的是MainActivity.onCreate的調用者,本例中它是performCreate函數。這部分代碼屬於Framework部分。Children行顯示的是MainActivity.onCreate調用的子函數。
  • 在MainActivity.onCreate調用的子函數中,我們發現getStringsToShow在 Incl Cpu Time %一列中佔據了63.3%,它是onCreate子函數耗費時間最長的,而且Calls+Recur Calls/Total列顯示其調用次數爲1,即它僅僅被調用一次了。這個函數是應用程序實現的,所以極有可能是一個潛在的Hotspot。
  • 另外,由於筆者已經知道getStringsToShow是示例應用自己實現的函數,故在圖1-6的大圖中,可直接根據MainActivity.getStringsToShow花費了2921.913CPU時間這個信息來確定Hotspot就是它。

相對來說,類型1hotspot比較好找,步驟是先按降序對時間項進行排列(可以是時間百分比、真實時間或CPU時間),然後查找耗費時間最多的函數。一般而言,先應對應用程序自己實現的函數進行排查,Framework的函數也有可能是hotspot,但主因一般還是在應用本身(例如設置複雜的界面,導致對應XML解析非常慢)。

現在,我們來看如何查找類型2hotspot

點擊Call/Recur Calls/Total列頭,使之按降序排列。關注點放在那些調用頻繁並且佔用資源較多的函數。圖1-7爲降序排列的結果圖。

Android系統性能調優工具介紹

1-7類型2 Hotspot查找過程示意之一

1-7所示的運行最頻繁的幾個函數中,我們發現了幾個懷疑點,由圖中的12箭頭標示。

  • 結合代碼,箭頭1所指的函數在代碼中實際並不存在。這是因爲代碼中直接訪問了內部類的私有成員,導致java編譯器 在編譯時自動生成了這個函數。這個函數的調用次數非常多。所以,爲了提高效率,我們可以修改內部類成員的訪問類型定義爲public。不過,該函數的 Incl Cpu Time並不高,只有3.2%。
  • 同樣,箭頭2所指部分的函數調用次數也很多,達到了5888多次。不過它們佔用的時間百分比只有0.9%。

第一次查找的潛在點被排除後,繼續瀏覽數據,得到如圖1-8所示的結果。

Android系統性能調優工具介紹

1-8  類型2 Hotspot查找過程示意之二

在圖1-8中:

  • 紅框處有兩個重載的MyMD5.getHashString函數調用,它們各運行了368次,而且佔用的CPU時間百分比達到了31.8%和53.2%。很顯然,這2處調用就有優化的餘地,這就是我們所懷疑的hotspot2。

找到hotspot之後,開發者就需要結合代碼來進行對應的優化了。關於Java代碼優化,讀者可參考如下資料:http://developer.android.com/training/articles/perf-tips.html

總體而言,Hotspot的查找是一個細緻的工作,需要開發者對目標程序的代碼,以及Traceview工具都比較熟悉才行。

1.3  Traceview小結

Traceview工具是Android平臺應用程序性能分析的利器。不過筆者覺得它的UI還是有些複雜。並且使用時感覺流暢度不夠好。

Google官方關於Traceview的介紹可參考以下鏈接,不過其內容以及較久未更新了。http://developer.android.com/tools/debugging/debugging-tracing.html

Systrace介紹

2.1  Systrace簡介

SystraceAndroid4.1中新增的性能數據採樣和分析工具。它可幫助開發者收集Android關鍵子系統(如surfaceflingerWindowManagerServiceFramework部分關鍵模塊、服務)的運行信息,從而幫助開發者更直觀的分析系統瓶頸,改進性能。

Systrace的功能包括跟蹤系統的I/O操作、內核工作隊列、CPU負載以及Android各個子系統的運行狀況等。在Android平臺中,它主要由3部分組成:

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

從本質上說,Systrace是對Linux Kernelftrace的封裝。應用進程需要利用Android提供的Trace類來使用SystraceAndroid 4.1爲系統中的幾個關鍵進程和模塊都添加了Systrace功能。以顯示系統中重要模塊Hwcomposer爲例,其代碼中使用Systrace的方法如圖2-1所示:

Android系統性能調優工具介紹 

2-1  Hwcomposer模塊Systrace使用示例

2-1中,應用程序只要通過三個宏就可使用Systrace了:

  • 定義ATRACE_TAG:Hwcomposer使用了ATRACE_TAG_GRAPHICS,表示它和Graphics相關。
  • ATRACE_INIT:用於統計某個變量使用的情況。下文將見到代碼中”VSYNC”的統計結果。
  • ATRACE_CALL:用於統計函數的調用情況。

由於篇幅關係,關於Trace使用更多的信息請讀者閱讀frameworks/native/include/utils/Trace.h或者android.os.Trace類。下面,我們通過一個示例來展示Systrace的使用。

2.2  Systrace實例

首先,在PC機上運行如下命令以啓動Systrace,如圖2-2所示:

Android系統性能調優工具介紹

2-2  Systrace操作步驟

執行上述命令後,將得到一個名爲trace.html的文件(trace.html是默認文件名,讀者也可在命令行中指定其他文件名)。通過瀏覽器打開此文件,結果如圖2-3所示:

Android系統性能調優工具介紹

 2-3  trace.html內容示意

2-3中所示的trace.html頁面內容和TraceviewTimeline Panel非常類似。圖中包含的內容如下:

  • 由於在systrace.py中指定了-f -l和-i參數,Systrace將生成CPU頻率、負載和狀態相關的信息。它們爲圖2-1中第一個紅框所示。由於筆者所測手機CPU爲雙核,故圖中有 CPU 0和CPU 1之分。爲行文方便,筆者用CPU N來指代CPU的某個核。
  • “CPU N“所示行對應於整個測試時間內,某個核上運行的進程信息。
  • “CPU N C-State“所示行爲整個測試時間內,某個CPU狀態的變化。C-State取值見表2-1。
  • “CPU N Clock Frequency”所示行展示了某個CPU運行的頻率。通過點擊這一行的色塊可以查看某個時間點上CPU N的運行頻率。
  • “cpufreq”:該行所示內容和CPU交互式頻率調節器(Interactive Governor)的工作有關。交互式CPU調節器驅動添加了對CPU頻率調節事件的跟蹤。感興趣的讀者不妨閱讀kernel中的 include/trace/events/cpufreq_interactive.h文件以瞭解更多的信息。

2-1中,CPU信息以下的行就是通過Trace.h提供的宏而添加的統計信息,其中:

  • VSYNC:這一行的統計信息來自於圖2-1中ATRACE_INIT宏的使用。在Hwcomposer代碼中,ATRACE_INIT宏被用於統計VSYNC[1]的Tick-Tack情況(即0,1,0,1交錯輸出)。VSYNC行顯示了每次Tick Tack的時間大概都在16ms左右。
  • 由於Framework代碼也在顯示部分添加了ATRACE_INIT的使用,所以圖中 com.example.systracedemo/com.example.systracedemo.MainActivity所示爲應用程序佔用顯 示Buffer的Tick-Tack情況。如果使用時間超過16ms,將導致界面顯示遲滯等現象。
  • SurfaceFlinger使用了ATRACE_CALL宏,故圖中SurfaceFlinger行展示了其函數調用的CPU耗時情況(如箭頭1所指,SurfaceFlinger中的onMessageReceived函數的運行信息)。
  • 在圖2-1最下部的方框中,詳細顯示了當前鼠標在時間線中選擇的部分(即SurfaceFlinger中的onMessageReceived)的詳細信息。

2-1所示爲CPU狀態取值信息:

2-1  CPU狀態

C-state

描述

C-0

RUN MODE,運行模式。

C-1

STANDBY,就位模式,隨時準備投入運行

C-2

DORMANT,休眠狀態,被喚醒投入運行時有一定的延遲

C-3

SHUTDOWN,關閉狀態,需要有較長的延遲才能進入運行狀態,減少耗電

2.3  Systrace小結

總體來說,SystraceTraceview用途更廣泛,它支持對CPUNative進程甚至Kernel線程進行性能數據採樣,可幫助開發者對整個系統的性能情況進行一個詳盡的分析。不過其用法比Traceview要複雜,而且還需要對Kernel做一些配置調整。

Android官方對Systrace也有一些介紹,請讀者閱讀:

http://developer.android.com/tools/debugging/systrace.html

Oprofile的使用

3.1  Oprofile簡介

Oprofile是另一個功能更強大的性能數據採集和分析工具,其工作原理如下:

  • 它利用性能計數器(Performance Counter)或者定時器(針對kernel不支持性能計數器的情況),通過連續的採樣獲得統計數據,從而對內核和用戶空間進程進行性能分析。
  • 以性能計數器爲例,在系統運行過程中,當某個事件發生時,對應的性能計數器就會自加。當達到計數器的設定值時會產生 一箇中斷。Oprofile驅動利用這個中斷來進行採樣統計。通過獲取中斷髮生時PC指針的值以及內核中保存運行的任務的信息等,並把它們轉化成對測評有 用的數據。
  • Oprofile包括內核驅動和用戶空間工具兩個部分,其中:
  • 內核驅動實現了一個oprofilefs虛擬文件系統。它掛載到/dev/oprofile,用來向用戶空間報告數 據和接收來自用戶空間的設置。它是用戶空間進程與內核通信的橋樑。驅動中還包括了與架構相關和通用的驅動,通過它們訪問性能計數器寄存器、收集數據後報告 給用戶空間。守護進程用戶從內核接收數據並保存在磁盤上以備分析使用。
  • 在用戶空間提供了兩個工具:oprofiled(作爲守護進程在後臺通過和/dev/oprofile交互以獲取驅動收集的數據)、opcontrol(用戶操作的控制工具,它通過讀寫oprofilefs來控制採樣相關的設置)。

Android默認提供了對Oprofile的支持,其組成包括:

  • 代碼:位於exetrnal/oprofile中。不過,只有編譯類型爲非user的系統纔會使用它。
  • 四個主要工具,即opcontrol,oprofiled、opreport和opimport。開發者只要使用opcontrol和opreport即可。
  • 讀者應該熟練掌握opcontroloprofiled工具的作用,我們此處也總結了它們的用法:
  • opcontrol:它用來控制採樣過程,比如採樣的開始和結束、採樣的事件類型和頻率等。其內部通過讀寫oprofilefs來實現。opcontrol的常用選項如表3-1所示:

3-1  opcontrol常用選項

opcontrol選項

功能

--list-events

列出當前CPU所支持的事件

--setup

對測評進行設置,比如關閉舊的守護進程、掛載oprofilefs

--vmlinux=

設置將要分析的Android內核鏡像文件

--callgraph

設置跟蹤函數調用的層數

--kernel-range=start,end

內核二進制文件起始和結束的虛擬地址

--start/--stop

開始/停止採樣

--event=name:count:unitmask:kernel:user

設置對某事件進行採樣。

Name:事件的名字

Count:採樣時事件發生的次數Unitmask:事件的掩碼(CPU支持的事件以及掩碼見oprofile的文檔)

Kernel:是否採樣內核事件

User:是否採樣用戶事件

  • opreport:opreport是使用採樣數據生成報告的工具,可根據用戶要求生成不同的報告。一般用法是 “opreport [options] [image]”,其中image指定報告需要顯示的程序的名字(指程序名字、共享庫名字和內核)。image參數可選。不指定它時,opreport將 打印所有進程的報告結果。常用options如表3-2所示:

3-2  opreport常用選項

opreprt選項

功能

-l

顯示函數調用的符號名字

-g

以調試的形式打印函數符號,包括函數所在文件及行數等。

-c

顯示函數調用堆棧

-o

報告輸出到指定文件

另外,Android提供了一個特別的工具opimport_pull。它可把採樣數據從手機中pullPC上,並對數據進行一些簡單處理以供opreport使用。所以,在Android平臺上,開發者只要使用opimport_pull了就可以了。

現在,我們來看Oprofile的使用實例。

3.2  Oprofile實例

Oprofile的使用大體可以分成以下三步:

  • 內核加載oprofile驅動(如果該驅動靜態編譯到內核中,則可略過此步驟)。
  • 配置採樣事件、然後進行採樣。
  • 獲取報告、進行分析,針對分析結果進行改進。

下面分別來看這三個步驟:

3.2.1  Oprofile內核配置

如下所示爲內核配置的示例,如圖3-1所示:

Android系統性能調優工具介紹

3-1  Oprofile內核配置示意

運行Oprofile需要root權限,所以目標設備中最好運行的是userdebug或者engineer版本的Android OS

3.2.2  Oprofile用戶空間配置

Oprofile用戶空間配置的示例如圖3-2所示。假設當前目錄爲Android源碼根目錄,並且已經初始化Android編譯環境(執行完畢build/envsetup.shlunch)。

Android系統性能調優工具介紹

3-2  Oprofile用戶空間配置示意

用戶空間的配置主要通過執行opcontrol命令來完成。而opcontrol內部是通過往oprofilefs傳遞對應的控制參數來完成的。例如圖3-2中“opcontrol --callgraph=16”命令也可通過“echo 16> /dev/oprofile/backtrace_depth”來實現。

3.2.3  結果分析

在上一步中,我們已經獲取了測評採樣的數據。現在,就可以使用它們來生成採樣報告了,方法如圖3-3所示:

Android系統性能調優工具介紹

3-3  oprofile生成採樣報告方法示意

3-4爲報告的一部分內容:

Android系統性能調優工具介紹

3-4  Oprofile測評報告概要

3-4中,我們發現libc.so調用的採樣數爲117299,排第4位。那麼libc.so中哪個函數調用次數最多呢?開發者可通過如下命令獲取libc.so的更爲詳細的信息。方法如圖3-5所示:

Android系統性能調優工具介紹

3-5  opreport使用示例

執行上述命令後的結果如圖3-6所示:

Android系統性能調優工具介紹

3-6  Oprofile關於libc的詳細結果

由圖3-6可知,memcpy()函數佔用最多的CPU資源。所以可以考慮優化memcpy()

此處,筆者針對Cortex-A9雙核SMP處理器,使用ARM彙編的方法對memcpy進行了優化。優化後的結果如圖3-7所示。對比圖3-6和圖3-7可明顯看出,優化後的memcpy對資源的佔用降低了2.7個百分點。

Android系統性能調優工具介紹

3-7  優化memcpy()後的測試結果

3.3  Oprofile小結

在性能分析中,Oprofile無疑是一個使用最廣泛、功能最強大的測評工具。對於Android平臺開發者來說,它可以採集和分析整個系統的運行狀態信息,對於分析查找系統瓶頸進而優化系統具有重大意義。

  總結

性能調優向來是一件“高深莫測”的任務,但打破它們神祕面紗的工具就是上文所述的工具了。所以,對有志開展這方面工作的讀者而言,首要一步的工作就是先了解各個工具的作用及優缺點。

除了本文介紹的這三個工具外,Android系統還支持其他一些更有針對性的測試工具,例如用於測評系統整體功能的lmbenchlttng、測試系統啓動性能的bootchart、測試文件系統性能的iozone等。由於篇幅關係,筆者就不再一一介紹它們了。

 [1]關於VSYNC的詳情,讀者可參考http://blog.csdn.net/innost/article/details/8272867,“Android Project Butter分析“一文。
來自:http://blog.csdn.net/innost/article/details/9008691

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