原創作者: Himi

 

由於本人現在在一家專職做網游的公司,所以現在需要使用一些方法對現運營的網游代碼進行精簡和優化,那麼就要使用到Android sdk中提供的一款很好的檢視工具—Android TraceView、下面先給出對此的解釋:然後講解實現的詳細步驟和需要特別注意的一點!

 

什麼是TraceView?先看下百度出來的解釋吧:



Traceview是android平臺配備一個很好的性能分析的工具。它可以通過圖形化的方式讓我們瞭解我們要跟蹤的程式的性能,並且能具體到method。

 

  關於Traceview的使用

 

  首先,必須在程式當中加入代碼,以便生成trace檔,有了這個trace檔才可以將其轉化為圖形。

 

  要添加的代碼如下:

 

  JAVA代碼

 

  // start tracing to "/sdcard/yourActivityTrace.trace"

 

  Debug.startMethodTracing("yourActivityTrace");

 

// ... // stop tracing Debug.stopMethodTracing();

 

// start tracing to "/sdcard/yourActivityTrace.trace" Debug.startMethodTracing("yourActivityTrace");

 

// ... // stop tracing Debug.stopMethodTracing();

 

  Google Dev Guide當中說可以在activity的onCreate()中添加Debug.startMethodTracing(), 而在onDestroy()中添加Debug.stopMethodTracing(),但是在實際的測試時發現這種方式其實並不好用,因為通常情況下我們的activity的onDestroy()是由系統決定何時調用的,因此可能等了很長時間都不會得到這個trace檔。因此決定在onStop()中來調用Debug.stopMethodTracing()。這樣當我們切換到其它activity或者點擊home鍵的時候onStop()就會被調用,我們也就可以得到完整的trace file。

 

  在運行程式之前,首先要保證我們的AVD是一個帶有SD card的AVD,這樣才能使trace檔保存到/sdcard/...當中。運行後可以任意做一些操作,然後點擊home鍵。這是通過DDMS file explore就可以看到/sdcard/目錄下有一個trace檔,現在把這個檔copy到電腦上指定的目錄,假設是C:\tracefile 目錄下。

 

  可以通過命令列來執行traceview,進入tools目錄後,執行

 

  traceview C:\tracefile\yourActivityTrace.trace

 

  之後就可以看到圖形了,接下來就是按照Google Dev Guide中的解釋去分析圖形就OK了。

 

下面來看如何實現以及需要注意的地方:

 

實現的步驟分為三步:1.必須先在我們的模擬器中創建sdCard ;2.將我們的調試代碼嵌入工程;3.利用TraceView來觀察和分析代碼情況;

 

1.對於創建模擬器的sdCard這裡寫出兩種方式:

 

第一種:我們在eclipse中創建avd的時候的時候 在選擇api下面有個 Sd Card 的選項,第一項填入創建sdcard的大小即可。

3a1f1471-75f5-3ff2-a377-6886bd0dd511  




第二種:cmd 命令! 打開cmd 並且cd 到android sdk tool 路徑下;(或者在環境變數Path中將sdk tool路徑配置上,然後重新打開cmd)

 

使用 mksdcard -l mycard 1024M F:\mysdcard.img 創建了一個1G的sdcard;

 

使用 emulator -avd my_android -sdcard F:\mysdcard.img 啟動sdcard!

 

最後在eclipse Preferences-->Android-->Launch加入 -sdcard F:\mysdcard.img (此步驟就是在第一種創建方式中添加sdcard的支援)



備註1:

 

如果sdcard分配的空間太小,則程式追蹤檔就一直記錄到sd儲蓄卡容量慢為止,所以調試前,要為程式生成一個適當的SD儲存卡也較為重要,因為程式執行時間越長,這個追蹤檔也就越大。





備註2;

 

(如果第二種創建方式中的第二部啟動出現 emulator: ERROR: the user data image is used by another emulator. aborting,請關閉模擬器,或者進入目錄: /Documents and Settings / 使用者 / .android /的AVD / *設備* / (比如我的目錄是:C:\Documents and Settings\Administrator\.android\avd\android2.0.avd)

 

然後刪去以.lock結尾的資料夾就行(我簡單解釋下為什麼要刪除這些檔呢,其實.lock是加鎖,如果程式崩潰等原因導致無法清除這些以.lock結尾的資料夾,就會出現這個問題,也就是這個avd的鎖沒有被釋放,導致avd manager以為這個avd正在使用當中。))




2.將我們的調試代碼嵌入工程

 

正如我們百度到的說明一樣,在程式運行的開端加上  Debug.startMethodTracing("yourActivityTrace"); 然後在onPause()中調用Debug.stopMethodTracing(); 為什麼要將結束寫在onPause()中而不寫在onStop(),那麼如果你去看api的話,你會看到,Api仲介紹onPause()會在你返回和點擊home按鍵後觸發,而onStop()一般是由系統來觸發,當該程式處於後臺的時候,而且當記憶體緊張的時候,可能會調用,但是可能永遠不會調用到!

 

備註:要記住當把調試代碼加入專案中以後不要立即運行專案,而是必須在AndroidMainfest.xml中定義一條"寫入SD卡的許可權"那麼添加許可權的代碼如下:

 

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

 

因為咱們的調試代碼會在SD卡中生成一個追蹤檔,也就是往SD卡中寫入了資料,所以需要聲明一條許可權。這裡必須注意哦!



JAVA代碼
1.<?xml version="1.0" encoding="utf-8"?>
2.<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3. package="com.himi"
4. android:versionCode="1"
5. android:versionName="1.0">
6. <application android:icon="@drawable/icon" android:label="@string/app_name">
7. <activity android:name=".MainActivity"
8. android:label="@string/app_name">
9. <intent-filter>
10. <action android:name="android.intent.action.MAIN" />
11. <category android:name="android.intent.category.LAUNCHER" />
12. </intent-filter>
13. </activity>
14. </application>
15. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
16. <uses-sdk android:minSdkVersion="4" />
17.</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.himi"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-sdk android:minSdkVersion="4" />
</manifest> 3.運行專案並且退出專案從而得到的追蹤檔,利用TraceView來進行分析代碼運行狀況:

 

打當正常運行了專案並且點擊返回或者home按鍵就會在 sdcard中生成一個.trace的檔。sdcard 目錄 在eclipse下,點擊:

 

windows-show view-other-android-File explorer

c424e8b1-38fb-3225-9d2c-8e59b8931ac3  


右上角的兩個箭頭,第一個表示從模擬器sdcard匯出檔,第二個表示從PC上導入檔到sdcard中、「—」代表刪除 .....
 
然後我們通過cmd來運行生成的追蹤檔 traceview C:\name 追蹤檔所在的路徑放在C盤,放在C盤以外別的盤的話我這裡是無法正常打開traceview的不知道什麼原因。 name 表示生成的.trace檔,cmd的時候不需要輸入「.trace」尾碼 ;然後會出現TraceView的分析視窗;

【cmd 命令! 打開cmd 並且cd 到android sdk tools 路徑下;(或者在環境變數Path中將sdk tool路徑配置上,然後重新打開cmd)】

注意1:如果出現一下圖片這種記憶體溢出的問題;

c0e49cf4-15ce-30b4-9366-7fde21edc922  


解決方法:到SDK 下的tools 下 找到 traceview.bat 檔,滑鼠右鍵-編輯(或者記事本打開),最後一行替換成這樣:

call java -Xms128m -Xmx512m -Djava.ext.dirs=%javaextdirs% -jar %jarpath% %*

注意2:如果出現路徑不對的問題:

例如:我的 himi.trace 放在了C盤,那麼我的cmd命令是: traceview c:\himi 然後回車!

但是這裡要小心,因為 \h 這樣可能被認為是逸出字元!!!為了避免可以盡可能不要使用h,n,r,t,等等成為名字的頭字母,當然還有一種就可以完全避免這種問題,例如還是我的C盤 himi.trace 檔,可以寫cmd命令的時候寫成: traceview c://himi 嘿嘿~要注意細節。

下面是運行起來的TranceView:
e11c5400-54c4-39c0-911c-ed9c8861b45e  



最右上角表示運行程式總共用了多少時間,從traceview畫面中我們看到有各種顏色,每種顏色代表不同的函數和步驟,那麼同一顏色的區域越大,就代表這個步驟執行時間越長,或者看到下面的統計表,明顯可以看出除了序列 0 1 是系統函數外,2. 3.函數 佔用的時間比較長,那麼序列4是個自訂的函數名為 「hot」這個佔用了幾乎與主執行緒 主draw的時間一樣了,那麼肯定有問題。當然其實這個方法是我故意寫的,就是為了來演示traceview。這個hot函數的代碼如下:


JAVA代碼
1./**
2. * @author Himi
3. * @param canvas
4. */
5. public void hot(Canvas canvas) {
6. for (int i = 1; i < 100; i++) {
7. Bitmap bmp = BitmapFactory.decodeResource(getResources(),
8. R.drawable.icon);
9. canvas.drawBitmap(bmp, i += 2, i += 2, paint);
10. }
11. }
/**
* @author Himi
* @param canvas
*/
public void hot(Canvas canvas) {
for (int i = 1; i < 100; i++) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
canvas.drawBitmap(bmp, i += 2, i += 2, paint);
}
} 很明顯我在故意消耗記憶體和時間。

那麼,在traceview的右半部統計欄位中:

Exclusive: 同級函數本身運行的時間

Inclusive 就是說除統計函數本身運行的時間外再加上調用子函數所運行的時間

Name:列出的是所有的調用項,前面的數位是編號,展開可以看到有的有Parent 和Children子項,就是指被調用和調用。

Incl: inclusive時間占總時間的白分比

Excl: 執行占總時間的白分比。

Calls+Recur Calls/Total: 調用和重複調用的次數


Time/Call: 總的時間。(ms)




所以traceview是個非常好的程式監視工具,可以説明找出程式運行緩慢時的函數,讓我們的代碼不斷完善和改進!
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()