鍍金池/ 教程/ Android/ 代碼性能優(yōu)化建議
檢測常用的手勢
優(yōu)化layout的層級(jí)
用戶輸入
管理應(yīng)用的內(nèi)存
聯(lián)系人信息
開發(fā)輔助程序
Android多媒體
添加語音功能
顯示位置地址
提供向下與橫向?qū)Ш?/span>
支持游戲控制器
訪問可穿戴數(shù)據(jù)層
處理多點(diǎn)觸控手勢
全屏沉浸式應(yīng)用
為多線程創(chuàng)建管理器
數(shù)據(jù)保存
Intent的發(fā)送
更新Notification
優(yōu)化下載以高效地訪問網(wǎng)絡(luò)
打印
打包可穿戴應(yīng)用
接收從其他App傳送來的數(shù)據(jù)
發(fā)送與接收消息
建立靈活動(dòng)態(tài)的UI
處理鍵盤輸入
Building a Work Policy Controller
建立測試環(huán)境
創(chuàng)建表盤
分享文件
顯示Notification進(jìn)度
實(shí)現(xiàn)自適應(yīng)UI流(Flows)
使用設(shè)備管理策略增強(qiáng)安全性
使用能感知版本的組件
執(zhí)行網(wǎng)絡(luò)操作
建立文件分享
添加移動(dòng)
更新你的Security Provider來對(duì)抗SSL漏洞利用
支持鍵盤導(dǎo)航
創(chuàng)建和監(jiān)視地理圍欄
發(fā)送并同步數(shù)據(jù)
使用BigView樣式
無線連接設(shè)備
提供向上導(dǎo)航與歷史導(dǎo)航
最小化定期更新造成的影響
實(shí)現(xiàn)向下的導(dǎo)航
支持不同的屏幕大小
Android 可穿戴應(yīng)用
添加動(dòng)畫
顯示聯(lián)系人頭像
使用OpenGL ES顯示圖像
處理輸入法可見性
分享文件
保持設(shè)備喚醒
淡化系統(tǒng)Bar
使用NFC分享文件
保存到Preference
Android聯(lián)系人信息與位置信息
創(chuàng)建標(biāo)準(zhǔn)的網(wǎng)絡(luò)請(qǐng)求
使用Drawables
管理Bitmap的內(nèi)存使用
管理Activity的生命周期
按需加載視圖
傳輸資源
為可穿戴設(shè)備創(chuàng)建自定義UI
在一個(gè)線程中執(zhí)行一段特定的代碼
性能優(yōu)化
隱藏導(dǎo)航欄
創(chuàng)建目錄瀏覽器
為多種大小的屏幕進(jìn)行規(guī)劃
View間漸變
使用觸摸手勢
高效加載大圖
使用CursorLoader在后臺(tái)加載數(shù)據(jù)
創(chuàng)建抽屜式導(dǎo)航(navigation drawer)
管理音頻焦點(diǎn)
創(chuàng)建后臺(tái)服務(wù)
創(chuàng)建功能測試
創(chuàng)建使用Material Design的應(yīng)用
停止與重啟Activity
添加一個(gè)簡便的分享功能
啟動(dòng)Activity時(shí)保留導(dǎo)航
TV應(yīng)用清單
創(chuàng)建向后兼容的UI
?# 優(yōu)化自定義View
創(chuàng)建單元測試
在UI上顯示Bitmap
建立OpenGL ES的環(huán)境
構(gòu)建表盤服務(wù)
JNI Tips
建立搜索界面
實(shí)現(xiàn)自定義View的繪制
使用HTTPS與SSL
按需操控BroadcastReceiver
分享簡單的數(shù)據(jù)
繪制形狀
Android位置信息
創(chuàng)建并運(yùn)行可穿戴應(yīng)用
執(zhí)行 Sync Adpater
獲取最后可知位置
創(chuàng)建 Android 項(xiàng)目
實(shí)現(xiàn)高效的導(dǎo)航
退出全屏的Activity
創(chuàng)建Card
兼容音頻輸出設(shè)備
同步數(shù)據(jù)單元
傳輸數(shù)據(jù)時(shí)避免消耗大量電量
保存到文件
緩存Bitmap
提供配置 Activity
調(diào)度重復(fù)的鬧鐘
實(shí)現(xiàn)輔助功能
重復(fù)的下載是冗余的
隱藏狀態(tài)欄
實(shí)現(xiàn)自定義的網(wǎng)絡(luò)請(qǐng)求
規(guī)劃界面和他們之間的關(guān)系
使用Sync Adapter傳輸數(shù)據(jù)
TV應(yīng)用內(nèi)搜索
響應(yīng)觸摸事件
使用Google Cloud Messaging(已廢棄)
控制相機(jī)
Android網(wǎng)絡(luò)連接與云服務(wù)
請(qǐng)求分享一個(gè)文件
處理TV硬件
響應(yīng)UI可見性的變化
使用網(wǎng)絡(luò)服務(wù)發(fā)現(xiàn)
指定輸入法類型
優(yōu)化電池壽命
創(chuàng)建TV應(yīng)用
獲取聯(lián)系人列表
拖拽與縮放
啟動(dòng)與停止線程池中的線程
創(chuàng)建 Sync Adpater
使用 WiFi P2P 服務(wù)發(fā)現(xiàn)
開始使用Material Design
代理至新的APIs
使用include標(biāo)簽重用layouts
使得View可交互
高效顯示Bitmap
創(chuàng)建企業(yè)級(jí)應(yīng)用
Fragments之間的交互
創(chuàng)建與執(zhí)行測試用例
綜合:設(shè)計(jì)我們的樣例 App
繪制表盤
建立簡單的用戶界面
自定義動(dòng)畫
開發(fā)輔助服務(wù)
避免出現(xiàn)程序無響應(yīng)ANR(Keeping Your App Responsive)
使用ViewPager實(shí)現(xiàn)屏幕滑動(dòng)
設(shè)計(jì)高效的導(dǎo)航
Android分享操作(Building Apps with Content Sharing)
提供向后的導(dǎo)航
保持向下兼容
創(chuàng)建TV播放應(yīng)用
縮放View
使用 WiFi 建立 P2P 連接
Android后臺(tái)任務(wù)
連接到網(wǎng)絡(luò)
為 Notification 添加頁面
使TV應(yīng)用是可被搜索的
添加Action Bar
使用Material的主題
啟動(dòng)另一個(gè)Activity
顯示正在播放卡片
適配不同的系統(tǒng)版本
輕松錄制視頻
創(chuàng)建可穿戴的應(yīng)用
創(chuàng)建自定義的布局
重新創(chuàng)建Activity
使用CursorLoader執(zhí)行查詢?nèi)蝿?wù)
使用舊的APIs實(shí)現(xiàn)新API的效果
使用備份API
安全要點(diǎn)
Android入門基礎(chǔ):從這里開始
保存并搜索數(shù)據(jù)
根據(jù)網(wǎng)絡(luò)連接類型來調(diào)整下載模式
使用Tabs創(chuàng)建Swipe視圖
SMP(Symmetric Multi-Processor) Primer for Android
解析 XML 數(shù)據(jù)
使用 Volley 傳輸網(wǎng)絡(luò)數(shù)據(jù)
建立ActionBar
Android交互設(shè)計(jì)
使用Intent修改聯(lián)系人信息
增加搜索功能
輕松拍攝照片
定義形狀
測試你的Activity
在 Notifcation 中接收語音輸入
與其他應(yīng)用的交互
管理系統(tǒng)UI
追蹤手勢移動(dòng)
Android界面設(shè)計(jì)
執(zhí)行 Android 程序
顯示確認(rèn)界面
創(chuàng)建Lists與Cards
打印HTML文檔
創(chuàng)建TV應(yīng)用
為多屏幕設(shè)計(jì)
定義Shadows與Clipping視圖
使用Fragment建立動(dòng)態(tài)UI
接收Activity返回的結(jié)果
布局變更動(dòng)畫
定位常見的問題
自定義ActionBar的風(fēng)格
定義Layouts
發(fā)送簡單的網(wǎng)絡(luò)請(qǐng)求
啟動(dòng)與銷毀Activity
與UI線程通信
非UI線程處理Bitmap
創(chuàng)建TV布局
提升Layout的性能
報(bào)告任務(wù)執(zhí)行狀態(tài)
判斷并監(jiān)測網(wǎng)絡(luò)連接狀態(tài)
兼容不同的設(shè)備
處理按鍵動(dòng)作
優(yōu)化性能和電池使用時(shí)間
給其他App發(fā)送簡單的數(shù)據(jù)
Implementing App Restrictions
向后臺(tái)服務(wù)發(fā)送任務(wù)請(qǐng)求
展示Card翻轉(zhuǎn)動(dòng)畫
管理ViewGroup中的觸摸事件
兼容不同的屏幕密度
通過藍(lán)牙進(jìn)行調(diào)試
為可穿戴設(shè)備創(chuàng)建Notification
控制音量與音頻播放
獲取聯(lián)系人詳情
在表盤上顯示信息
提供向上的導(dǎo)航
滾動(dòng)手勢動(dòng)畫
幫助用戶在TV上找到內(nèi)容
創(chuàng)建TV導(dǎo)航
為索引指定App內(nèi)容
ActionBar的覆蓋疊加
Android Wear 上的位置檢測
保護(hù)安全與隱私的最佳策略
Ensuring Compatibility with Managed Profiles
解決云同步的保存沖突
獲取位置更新
創(chuàng)建List
測試程序
管理網(wǎng)絡(luò)的使用情況
為App內(nèi)容開啟深度鏈接
推薦TV內(nèi)容
建立一個(gè)Notification
管理音頻播放
設(shè)計(jì)表盤
拍照
處理控制器輸入動(dòng)作
判斷并監(jiān)測設(shè)備的底座狀態(tài)與類型
處理查詢的結(jié)果
保存到數(shù)據(jù)庫
支持多個(gè)游戲控制器
創(chuàng)建 Stub Content Provider
使得ListView滑動(dòng)順暢
處理數(shù)據(jù)層的事件
創(chuàng)建TV應(yīng)用的第一步
使得你的App內(nèi)容可被Google搜索
將 Notification 放成一疊
創(chuàng)建 Stub 授權(quán)器
暫停與恢復(fù)Activity
管理設(shè)備的喚醒狀態(tài)
Android圖像與動(dòng)畫
打印照片
云同步
創(chuàng)建TV直播應(yīng)用
為Notification賦加可穿戴特性
提供一個(gè)Card視圖
建立請(qǐng)求隊(duì)列(RequestQueue)
適配不同的語言
創(chuàng)建詳情頁
測試UI組件
接收其他設(shè)備的文件
創(chuàng)建自定義View
建立第一個(gè)App
創(chuàng)建2D Picker
監(jiān)測電池的電量與充電狀態(tài)
打印自定義文檔
抽象出新的APIs
通知提示用戶
獲取文件信息
運(yùn)用投影與相機(jī)視角
在IntentService中執(zhí)行后臺(tái)任務(wù)
多線程操作
創(chuàng)建一個(gè)Fragment
添加Action按鈕
在不同的 Android 系統(tǒng)版本支持控制器
維護(hù)兼容性
發(fā)送文件給其他設(shè)備
創(chuàng)建TV游戲應(yīng)用
創(chuàng)建自定義的View類
代碼性能優(yōu)化建議
Intent過濾
適配不同的屏幕

代碼性能優(yōu)化建議

編寫:kesenhoo - 原文:http://developer.android.com/training/articles/perf-tips.html

這篇文章主要介紹一些小細(xì)節(jié)的優(yōu)化技巧,雖然這些小技巧不能較大幅度的提升應(yīng)用性能,但是恰當(dāng)?shù)倪\(yùn)用這些小技巧并發(fā)生累積效應(yīng)的時(shí)候,對(duì)于整個(gè)App的性能提升還是有不小作用的。通常來說,選擇合適的算法與數(shù)據(jù)結(jié)構(gòu)會(huì)是你首要考慮的因素,在這篇文章中不會(huì)涉及這方面的知識(shí)點(diǎn)。你應(yīng)該使用這篇文章中的小技巧作為平時(shí)寫代碼的習(xí)慣,這樣能夠提升代碼的效率。

通常來說,高效的代碼需要滿足下面兩個(gè)原則:

  • 不要做冗余的工作
  • 盡量避免執(zhí)行過多的內(nèi)存分配操作

在優(yōu)化App時(shí)其中一個(gè)難點(diǎn)就是讓App能在各種型號(hào)的設(shè)備上運(yùn)行。不同版本的虛擬機(jī)在不同的處理器上會(huì)有不同的運(yùn)行速度。你甚至不能簡單的認(rèn)為“設(shè)備X的速度是設(shè)備Y的F倍”,然后還用這種倍數(shù)關(guān)系去推測其他設(shè)備。另外,在模擬器上的運(yùn)行速度和在實(shí)際設(shè)備上的速度沒有半點(diǎn)關(guān)系。同樣,設(shè)備有沒有JIT也對(duì)運(yùn)行速度有重大影響:在有JIT情況下的最優(yōu)化代碼不一定在沒有JIT的情況下也是最優(yōu)的。

為了確保App在各設(shè)備上都能良好運(yùn)行,就要確保你的代碼在不同檔次的設(shè)備上都盡可能的優(yōu)化。

避免創(chuàng)建不必要的對(duì)象

創(chuàng)建對(duì)象從來不是免費(fèi)的。Generational GC可以使臨時(shí)對(duì)象的分配變得廉價(jià)一些,但是執(zhí)行分配內(nèi)存總是比不執(zhí)行分配操作更昂貴。

隨著你在App中分配更多的對(duì)象,你可能需要強(qiáng)制gc,而gc操作會(huì)給用戶體驗(yàn)帶來一點(diǎn)點(diǎn)卡頓。雖然從Android 2.3開始,引入了并發(fā)gc,它可以幫助你顯著提升gc的效率,減輕卡頓,但畢竟不必要的內(nèi)存分配操作還是應(yīng)該盡量避免。

因此請(qǐng)盡量避免創(chuàng)建不必要的對(duì)象,有下面一些例子來說明這個(gè)問題:

  • 如果你需要返回一個(gè)String對(duì)象,并且你知道它最終會(huì)需要連接到一個(gè)StringBuffer,請(qǐng)修改你的函數(shù)實(shí)現(xiàn)方式,避免直接進(jìn)行連接操作,應(yīng)該采用創(chuàng)建一個(gè)臨時(shí)對(duì)象來做字符串的拼接這個(gè)操作。
  • 當(dāng)從已經(jīng)存在的數(shù)據(jù)集中抽取出String的時(shí)候,嘗試返回原數(shù)據(jù)的substring對(duì)象,而不是創(chuàng)建一個(gè)重復(fù)的對(duì)象。使用substring的方式,你將會(huì)得到一個(gè)新的String對(duì)象,但是這個(gè)string對(duì)象是和原string共享內(nèi)部char[]空間的。

一個(gè)稍微激進(jìn)點(diǎn)的做法是把所有多維的數(shù)據(jù)分解成一維的數(shù)組:

  • 一組int數(shù)據(jù)要比一組Integer對(duì)象要好很多??梢缘弥?,兩組一維數(shù)組要比一個(gè)二維數(shù)組更加的有效率。同樣的,這個(gè)道理可以推廣至其他原始數(shù)據(jù)類型。
  • 如果你需要實(shí)現(xiàn)一個(gè)數(shù)組用來存放(Foo,Bar)的對(duì)象,記住使用Foo[]與Bar[]要比(Foo,Bar)好很多。(例外的是,為了某些好的API的設(shè)計(jì),可以適當(dāng)做一些妥協(xié)。但是在自己的代碼內(nèi)部,你應(yīng)該多多使用分解后的容易)。

通常來說,需要避免創(chuàng)建更多的臨時(shí)對(duì)象。更少的對(duì)象意味者更少的gc動(dòng)作,gc會(huì)對(duì)用戶體驗(yàn)有比較直接的影響。

選擇Static而不是Virtual

如果你不需要訪問一個(gè)對(duì)象的值,請(qǐng)保證這個(gè)方法是static類型的,這樣方法調(diào)用將快15%-20%。這是一個(gè)好的習(xí)慣,因?yàn)槟憧梢詮姆椒暶髦械弥{(diào)用無法改變這個(gè)對(duì)象的狀態(tài)。

常量聲明為Static Final

考慮下面這種聲明的方式

static int intVal = 42;
static String strVal = "Hello, world!";

編譯器會(huì)使用一個(gè)初始化類的函數(shù),然后當(dāng)類第一次被使用的時(shí)候執(zhí)行。這個(gè)函數(shù)將42存入intVal,還從class文件的常量表中提取了strVal的引用。當(dāng)之后使用intValstrVal的時(shí)候,他們會(huì)直接被查詢到。

我們可以用final關(guān)鍵字來優(yōu)化:

static final int intVal = 42;
static final String strVal = "Hello, world!";

這時(shí)再也不需要上面的方法了,因?yàn)閒inal聲明的常量進(jìn)入了靜態(tài)dex文件的域初始化部分。調(diào)用intVal的代碼會(huì)直接使用42,調(diào)用strVal的代碼也會(huì)使用一個(gè)相對(duì)廉價(jià)的“字符串常量”指令,而不是查表。

Notes:這個(gè)優(yōu)化方法只對(duì)原始類型和String類型有效,而不是任意引用類型。不過,在必要時(shí)使用static final是個(gè)很好的習(xí)慣。

避免內(nèi)部的Getters/Setters

像C++等native language,通常使用getters(i = getCount())而不是直接訪問變量(i = mCount)。這是編寫C++的一種優(yōu)秀習(xí)慣,而且通常也被其他面向?qū)ο蟮恼Z言所采用,例如C#與Java,因?yàn)榫幾g器通常會(huì)做inline訪問,而且你需要限制或者調(diào)試變量,你可以在任何時(shí)候在getter/setter里面添加代碼。

然而,在Android上,這不是一個(gè)好的寫法。虛函數(shù)的調(diào)用比起直接訪問變量要耗費(fèi)更多。在面向?qū)ο缶幊讨校瑢etter和setting暴露給公用接口是合理的,但在類內(nèi)部應(yīng)該僅僅使用域直接訪問。

在沒有JIT(Just In Time Compiler)時(shí),直接訪問變量的速度是調(diào)用getter的3倍。有JIT時(shí),直接訪問變量的速度是通過getter訪問的7倍。

請(qǐng)注意,如果你使用ProGuard,你可以獲得同樣的效果,因?yàn)镻roGuard可以為你inline accessors.

使用增強(qiáng)的For循環(huán)

增強(qiáng)的For循環(huán)(也被稱為 for-each 循環(huán))可以被用在實(shí)現(xiàn)了 Iterable 接口的 collections 以及數(shù)組上。使用collection的時(shí)候,Iterator會(huì)被分配,用于for-each調(diào)用hasNext()next()方法。使用ArrayList時(shí),手寫的計(jì)數(shù)式for循環(huán)會(huì)快3倍(不管有沒有JIT),但是對(duì)于其他collection,增強(qiáng)的for-each循環(huán)寫法會(huì)和迭代器寫法的效率一樣。

請(qǐng)比較下面三種循環(huán)的方法:

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}
  • zero()是最慢的,因?yàn)镴IT沒有辦法對(duì)它進(jìn)行優(yōu)化。
  • one()稍微快些。
  • two() 在沒有做JIT時(shí)是最快的,可是如果經(jīng)過JIT之后,與方法one()是差不多一樣快的。它使用了增強(qiáng)的循環(huán)方法for-each。

所以請(qǐng)盡量使用for-each的方法,但是對(duì)于ArrayList,請(qǐng)使用方法one()。

Tips:你還可以參考 Josh Bloch 的 《Effective Java》這本書的第46條

使用包級(jí)訪問而不是內(nèi)部類的私有訪問

參考下面一段代碼

public class Foo {
    private class Inner {
        void stuff() {
            Foo.this.doStuff(Foo.this.mValue);
        }
    }

    private int mValue;

    public void run() {
        Inner in = new Inner();
        mValue = 27;
        in.stuff();
    }

    private void doStuff(int value) {
        System.out.println("Value is " + value);
    }
}

這里重要的是,我們定義了一個(gè)私有的內(nèi)部類(Foo$Inner),它直接訪問了外部類中的私有方法以及私有成員對(duì)象。這是合法的,這段代碼也會(huì)如同預(yù)期一樣打印出"Value is 27"。

問題是,VM因?yàn)?code>Foo和Foo$Inner是不同的類,會(huì)認(rèn)為在Foo$Inner中直接訪問Foo類的私有成員是不合法的。即使Java語言允許內(nèi)部類訪問外部類的私有成員。為了去除這種差異,編譯器會(huì)產(chǎn)生一些仿造函數(shù):

/*package*/ static int Foo.access$100(Foo foo) {
    return foo.mValue;
}
/*package*/ static void Foo.access$200(Foo foo, int value) {
    foo.doStuff(value);
}

每當(dāng)內(nèi)部類需要訪問外部類中的mValue成員或需要調(diào)用doStuff()函數(shù)時(shí),它都會(huì)調(diào)用這些靜態(tài)方法。這意味著,上面的代碼可以歸結(jié)為,通過accessor函數(shù)來訪問成員變量。早些時(shí)候我們說過,通過accessor會(huì)比直接訪問域要慢。所以,這是一個(gè)特定語言用法造成性能降低的例子。

如果你正在性能熱區(qū)(hotspot:高頻率、重復(fù)執(zhí)行的代碼段)使用像這樣的代碼,你可以把內(nèi)部類需要訪問的域和方法聲明為包級(jí)訪問,而不是私有訪問權(quán)限。不幸的是,這意味著在相同包中的其他類也可以直接訪問這些域,所以在公開的API中你不能這樣做。

避免使用float類型

Android系統(tǒng)中float類型的數(shù)據(jù)存取速度是int類型的一半,盡量優(yōu)先采用int類型。

就速度而言,現(xiàn)代硬件上,float 和 double 的速度是一樣的??臻g而言,double 是兩倍float的大小。在空間不是問題的情況下,你應(yīng)該使用 double 。

同樣,對(duì)于整型,有些處理器實(shí)現(xiàn)了硬件幾倍的乘法,但是沒有除法。這時(shí),整型的除法和取余是在軟件內(nèi)部實(shí)現(xiàn)的,這在你使用哈希表或大量計(jì)算操作時(shí)要考慮到。

使用庫函數(shù)

除了那些常見的讓你多使用自帶庫函數(shù)的理由以外,記得系統(tǒng)函數(shù)有時(shí)可以替代第三方庫,并且還有匯編級(jí)別的優(yōu)化,他們通常比帶有JIT的Java編譯出來的代碼更高效。典型的例子是:Android API 中的 String.indexOf(),Dalvik出于內(nèi)聯(lián)性能考慮將其替換。同樣 System.arraycopy()函數(shù)也被替換,這樣的性能在Nexus One測試,比手寫的for循環(huán)并使用JIT還快9倍。

Tips:參見 Josh Bloch 的 《Effective Java》這本書的第47條

謹(jǐn)慎使用native函數(shù)

結(jié)合Android NDK使用native代碼開發(fā),并不總是比Java直接開發(fā)的效率更好的。Java轉(zhuǎn)native代碼是有代價(jià)的,而且JIT不能在這種情況下做優(yōu)化。如果你在native代碼中分配資源(比如native堆上的內(nèi)存,文件描述符等等),這會(huì)對(duì)收集這些資源造成巨大的困難。你同時(shí)也需要為各種架構(gòu)重新編譯代碼(而不是依賴JIT)。你甚至對(duì)已同樣架構(gòu)的設(shè)備都需要編譯多個(gè)版本:為G1的ARM架構(gòu)編譯的版本不能完全使用Nexus One上ARM架構(gòu)的優(yōu)勢,反之亦然。

Native 代碼是在你已經(jīng)有本地代碼,想把它移植到Android平臺(tái)時(shí)有優(yōu)勢,而不是為了優(yōu)化已有的Android Java代碼使用。

如果你要使用JNI,請(qǐng)學(xué)習(xí)JNI Tips

Tips:參見 Josh Bloch 的 《Effective Java》這本書的第54條

關(guān)于性能的誤區(qū)

在沒有JIT的設(shè)備上,使用一種確切的數(shù)據(jù)類型確實(shí)要比抽象的數(shù)據(jù)類型速度要更有效率(例如,調(diào)用HashMap map要比調(diào)用Map map效率更高)。有誤傳效率要高一倍,實(shí)際上只是6%左右。而且,在JIT之后,他們直接并沒有大多差異。

在沒有JIT的設(shè)備上,讀取緩存域比直接讀取實(shí)際數(shù)據(jù)大概快20%。有JIT時(shí),域讀取和本地讀取基本無差。所以優(yōu)化并不值得除非你覺得能讓你的代碼更易讀(這對(duì) final, static, static final 域同樣適用)。

關(guān)于測量

在優(yōu)化之前,你應(yīng)該確定你遇到了性能問題。你應(yīng)該確保你能夠準(zhǔn)確測量出現(xiàn)在的性能,否則你也不會(huì)知道優(yōu)化是否真的有效。

本章節(jié)中所有的技巧都需要Benchmark(基準(zhǔn)測試)的支持。Benchmark可以在 code.google.com "dalvik" project 中找到

Benchmark是基于Java版本的 Caliper microbenchmarking框架開發(fā)的。Microbenchmarking很難做準(zhǔn)確,所以Caliper幫你完成這部分工作,甚至還幫你測了你沒想到需要測量的部分(因?yàn)?,VM幫你管理了代碼優(yōu)化,你很難知道這部分優(yōu)化有多大效果)。我們強(qiáng)烈推薦使用Caliper來做你的基準(zhǔn)微測工作。

我們也可以用Traceview 來測量,但是測量的數(shù)據(jù)是沒有經(jīng)過JIT優(yōu)化的,所以實(shí)際的效果應(yīng)該是要比測量的數(shù)據(jù)稍微好些。

關(guān)于如何測量與調(diào)試,還可以參考下面兩篇文章:

上一篇:支持游戲控制器下一篇:測試程序