優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計_第1頁
優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計_第2頁
優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計_第3頁
優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計_第4頁
優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計_第5頁
已閱讀5頁,還剩5頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、.1優(yōu)就業(yè)Android教程-Android應(yīng)用程序運行的性能設(shè)計Android應(yīng)用程序運行的移動設(shè)備受限于其運算能力,存儲空間,及電池續(xù)航。由此,它必須是高效的。電池續(xù)航可能是一個促使你優(yōu)化程序的原因,即使他看起來已經(jīng)運行的足夠快了。由于續(xù)航對用戶的重要性,當電量耗損陡增時,意味這用戶遲早會發(fā)現(xiàn)是由于你的程序。雖然這份文檔主要包含著細微的優(yōu)化,但這些絕不能成為你軟件成敗的關(guān)鍵。選擇適宜的算法和數(shù)據(jù)構(gòu)造永遠是你最先應(yīng)該考慮的事情,但這超出這份文檔之外。1. 介紹寫出高效的代碼有兩條根本的原則: 不作沒有必要的工作 盡量防止存分配。2. 明智的優(yōu)化這份文檔是關(guān)于Android規(guī)的細微優(yōu)化,所以先

2、確保你已經(jīng)了解哪些代碼需要優(yōu)化,并且知道如何去衡量你所做修改所帶來的效果(好或壞)。用開投資開發(fā)的時間是有限的,所以明智的時間規(guī)劃很重要。這份文檔同時確保你在算法和數(shù)據(jù)構(gòu)造上作出最正確選擇,同時考慮了API選擇所帶來的潛在影響。使用恰當?shù)臄?shù)據(jù)構(gòu)造和算法比這里的任何建議都有價值,考慮API版本帶來的影響會如實你選擇更好的實現(xiàn)。當你優(yōu)化Android程序時會遇到的一個棘手問題是確保你的程序能在不同的硬件平臺上運行。不同版本的虛擬機在不同處理器上的運行速度各不一樣。并且不是簡單的設(shè)備A比設(shè)備B快或者慢,并針對一個設(shè)備與其他設(shè)備之間做出排列。特別的,模擬器上只能評測小局部可以在設(shè)備上表達的東西。有無J

3、IT的設(shè)備間也有著巨大差異:對于有JIT設(shè)備好的代碼有時對無JIT的設(shè)備并不是最好的。如果你想知道程序在設(shè)備上的表現(xiàn),就必須在上面進展測試3. 防止創(chuàng)立不必要的對象對象創(chuàng)立永遠不會免費的。每個線程的分代GC給臨時對象分配一個地址池能降低分配開銷,但分配存往往需要比不分配存高的代價。如果在用戶界面周期分配對象,會強制一個周期性的垃圾回收,給用戶體驗造成小小的停頓間隙。Gingerbread中介紹的并發(fā)回收也許有用,但應(yīng)該防止不必要的工作。因此,防止創(chuàng)立不需要的對象實例。下面是幾個例子: 如果有一個返回String的方法,他的返回值通常附加在一個StringBuffer上,改變聲明和實現(xiàn),這樣函數(shù)

4、直接在其后面附加,而非創(chuàng)立一個短暫存在的臨時變量。 當從輸入的數(shù)據(jù)集合中讀取數(shù)據(jù)時,考慮返回原始數(shù)據(jù)的子串,而非新建一個拷貝。這樣你會創(chuàng)立一個新的對象,但是他們共享該數(shù)據(jù)的char數(shù)組。換來的是即使你僅僅使用原始輸入的一局部,你也需要保證它一直存在于存中。一個更徹底的觀點是將多維數(shù)組切割成一維數(shù)組: Int類型的數(shù)組比Integer類型的好。推而廣之,兩個平行的int數(shù)組要比一個(int,int)型的對象數(shù)組高效。這個定理對于任何根本數(shù)據(jù)類型的組合都通用。 如果需要實現(xiàn)存放元組(Foo,Bar)對象的容器,記住兩個平行數(shù)組Foo, Bar會優(yōu)于一個(Foo,Bar)對象的數(shù)組。(例外情況是:當

5、你設(shè)計API給其他代碼調(diào)用時,最好用好的API設(shè)計來換取小的速度提升。但在自己的部代碼中,盡量嘗試高效的實現(xiàn)。)通常來說,盡量防止創(chuàng)立短時臨時對象。少的對象創(chuàng)立意味著低頻的垃圾回收。這對于用戶體驗產(chǎn)生直接的影響。4. 性能之謎前一個版本的文檔給出了好多誤導人的主,這里做一些澄清: 在沒有JIT的設(shè)備上,調(diào)用方法所傳遞的對象采用具體的類型而非接口類型會更有效(比方,傳遞HashMap map比傳遞Map map調(diào)用一個方法消耗的開銷小,盡管兩種情況下的map都是HashMap)。但這并不是兩倍慢的情形,事實上,只相差6%,而JIT使這兩種調(diào)用的效率不分伯仲。 在沒有JIT的設(shè)備上,緩存后的字段比

6、直接字段快大概20%。在有JIT的情況下,字段和局部消耗是一樣的 。所以這里不值得優(yōu)化,除非你覺得他會讓你的代碼更易讀(對于final,static,及static final 變量同樣適用).5. 用靜態(tài)代替虛擬如果不需要*對象的字段,將方法設(shè)置為靜態(tài),調(diào)用會加速15%到20%。這也是一種好的做法,因為你可以通過方法聲明知曉調(diào)用該方法不需要更新此對象的狀態(tài)。6. 防止部的Getters/Setters在源生語言像C+中,通常做法是用Getters(i=getCount()代替直接字段(i=mCount)。這是C+中一個好的習慣,因為編譯器會聯(lián)這些,如果需要約束或者調(diào)試這些域的,你可以在任何時

7、間添加代碼。在Android中,這是個不好的想法。虛方法調(diào)用代價比直接存取字段高昂的多。按照通常面向?qū)ο笳Z言的做法在公共接口中使用Getters和Setters是有原因的,但應(yīng)該在一個經(jīng)常其字段的類中采用直接。無JIT時,直接字段大約比調(diào)用無關(guān)緊要的getter來快3倍。有JIT時(直接字段開銷和局部變量是一樣的),要快7倍。在Froyo版本中確實如此,但以后會在JIT中改進Getter方法的聯(lián)。7. 對常量使用Static Final修飾符考慮下面類首的聲明:Java代碼static int intVal = 42; static String strVal = Hello, world!;

8、編譯器生成一個類初始化方法clinit, 當類初次被使用時執(zhí)行,這個方法將42存入intVal中,并得到類字符串常量strVal的引用。當這些值在后面被引用時,他們通過字段查找進展。我們改進實現(xiàn),采用 final關(guān)鍵字:Java代碼static final int intVal = 42; static final String strVal = Hello, world!;類不再需要clinit方法,因為常量進入了de*文件中的靜態(tài)字段初始化器中。引用intVal的代碼,直接調(diào)用整形值42,而strVal時也會采用相對開銷較小的 string constant(字符串常量)指令替代字段查找。

9、(這種優(yōu)化僅僅是針對根本數(shù)據(jù)類型和String類型常量的,而非任意的引用類型。但盡可能的將常量聲明為static final類型是一種好的做法。8. 使用改進的For循環(huán)語法改進的for循環(huán)(有時被稱為for-each循環(huán))能夠用于實現(xiàn)了iterable接口的集合類及數(shù)組中。在集合類中,迭代器促使接口hasNe*t()和ne*t()方法,在ArrayList中,計數(shù)循環(huán)迭代要快3倍(無論有沒有JIT),但其他集合類中,改進的for循環(huán)語法和迭代器具有一樣的效率。這里有一些迭代數(shù)組的實現(xiàn):Java代碼static class Foo int mSplat; Foo mArray = . publ

10、ic void zero() int sum = 0; for (int i = 0; i mArray.length; +i) sum += mArrayi.mSplat; public void one() int sum = 0; Foo localArray = mArray; int len = localArray.length; for (int i = 0; i len; +i) sum += localArrayi.mSplat; public void two() int sum = 0; for (Foo a : mArray) sum += a.mSplat; zero

11、()是當中最慢的,因為對于這個遍歷中的歷次迭代,JIT不能優(yōu)化獲取數(shù)組長度的開銷。One()稍快,將所有東西都放進局部變量中,防止了查找。但僅只有數(shù)組長度促使了性能的改善。Two()是在無JIT的設(shè)備上運行最快的,對于有JIT的設(shè)備則和one()不分上下。他采用了JDK1.5中的改進for循環(huán)語法。結(jié)論:優(yōu)先采用改進的for循環(huán),但在性能要求苛刻的ArrayList迭代中考慮采用手寫計數(shù)循環(huán)。9. 在私有部中,考慮用包權(quán)限替代私有權(quán)限考慮下面的定義:Java代碼public class Foo private class Inner void stuff() Foo.this.doStuff(

12、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); 需要注意的關(guān)鍵是:我們定義的一個私有部類(Foo$Inner)直接外部類中的一個私有方法和私有變量。這是合法的,代碼也會打印出預期的Value is 27。但問題是虛擬機認為從Foo$Inner中直接Foo的私有成員是非法的,因為他們是兩個不同的類,

13、盡管Java語言允許部類外部類的私有成員,編譯器生成幾個綜合方法來橋接這些間隙。Java代碼/*package*/ static int Foo.access$100(Foo foo) return foo.mValue; /*package*/ static void Foo.access$200(Foo foo, int value) foo.doStuff(value); 部類會在外部類中任何需要mValue字段或者doStuff方法的地方調(diào)用這些靜態(tài)方法。這意味著這些代碼將直接存取成員變量歸結(jié)為通過存取器方法。之前提到存取器如何比直接慢,這例子說明,*些語言約定導致了不可見的性能問題。

14、如果你在高性能的Hotspot中使用這些代碼,可以通過聲明被部類的字段和成員為包權(quán)限,而非私有。不幸的是這意味著這些字段會被其他處于同一個包中的類,因此在公共API中不宜采用。10. 合理利用浮點數(shù)通常的經(jīng)歷是,在Android設(shè)備中,浮點數(shù)會比整型慢兩倍,在缺少FPU,或是JIT的G1以及有FPU和JIT的Ne*us One中確實如此(兩種設(shè)備間算數(shù)運算的絕對速度差大約是10倍).速度術(shù)語中,在現(xiàn)代硬件上,float和double之間并沒有不同。更廣泛的講,double大約2倍大。在沒有存儲空間問題的桌面機器中,double的優(yōu)先級高于float。但即使是整型,有些芯片擁有硬件乘法,卻缺少除

15、法。這種情況下,整型除法和求模運算是通過軟件實現(xiàn)的,考慮下當你設(shè)計Hash表,或是做大量的算術(shù)。11. 了解并使用類庫除了通常的那些有限選擇類庫代碼而非自己的原因外,考慮到系統(tǒng)空閑時用手寫的匯編程序來替代類庫方法,這可能比JIT中能生成的最好的等效Java代碼還要好。典型的例子就是String.inde*Of,Dalvik用部聯(lián)來替代。同樣的,System.arraycopy方法比Ne*us One中有JIT的自行編碼循環(huán)快9倍.12. 合理利用本地方法本地方法并不是一定比Java高效,至少,Java和native之間過渡的關(guān)聯(lián)是有消耗的。而JIT并不能越過這個界限進展優(yōu)化。當你分配本地資源時

16、(本地堆上的存,文件說明符等),往往很難實時的回收這些資源。同時你也需要在各個構(gòu)造中編譯你的代碼,而非依賴JIT。甚至可能需要針對一樣的架構(gòu)來編譯出不同版本:針對ARM處理器的GI編譯的本地代碼,并不能充分利用Ne*us One上的ARM,而針對Ne*us One上ARM編譯的本地代碼不能在G1的ARM上運行。當存在有你想部署到Android上的本地代碼庫時,本地代碼顯得尤為有用,而非為了Java應(yīng)用程序的提速。結(jié)語最后:通常權(quán)衡的,先確定存在問題,再進展優(yōu)化。確認你知道當前的性能,否則無法衡量你進展嘗試所得到的提升。這份文檔中的每個主都有基準測試作為支持。你可以在code.google.的dalvik工程

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論