本文為性能優(yōu)化系列的總綱荒适,主要介紹性能調(diào)優(yōu)專題計(jì)劃梨熙、何為性能問題、性能調(diào)優(yōu)方式及前面介紹的數(shù)據(jù)庫優(yōu)化刀诬、布局優(yōu)化咽扇、Java(Android)代碼優(yōu)化、網(wǎng)絡(luò)優(yōu)化具體對(duì)應(yīng)的調(diào)優(yōu)方式。
1质欲、降低執(zhí)行時(shí)間
這部分包括:緩存树埠、數(shù)據(jù)存儲(chǔ)優(yōu)化、算法優(yōu)化嘶伟、JNI怎憋、邏輯優(yōu)化、需求優(yōu)化幾種優(yōu)化方式九昧。
(1). 緩存
緩存主要包括對(duì)象緩存绊袋、IO緩存、網(wǎng)絡(luò)緩存铸鹰、DB緩存癌别,對(duì)象緩存能減少內(nèi)存的分配,IO緩存減少磁盤的讀寫次數(shù)掉奄,網(wǎng)絡(luò)緩存減少網(wǎng)絡(luò)傳輸规个,DB緩存較少Database的訪問次數(shù)。
在內(nèi)存姓建、文件、數(shù)據(jù)庫缤苫、網(wǎng)絡(luò)的讀寫速度中速兔,內(nèi)存都是最優(yōu)的,且速度數(shù)量級(jí)差別活玲,所以盡量將需要頻繁訪問或訪問一次消耗較大的數(shù)據(jù)存儲(chǔ)在緩存中涣狗。
Android中常使用緩存:
a.線程池
b.Android圖片緩存,Android圖片Sdcard緩存舒憾,數(shù)據(jù)預(yù)取緩存
c. 消息緩存
通過handler.obtainMessage復(fù)用之前的message镀钓,如下:
handler.sendMessage(handler.obtainMessage(0,object));
數(shù)據(jù)庫緩存http response,根據(jù)http頭信息中的Cache-Control域確定緩存過期時(shí)間镀迂。
f. 文件IO緩存
使用具有緩存策略的輸入流丁溅,BufferedInputStream替代InputStream,BufferedReader替代Reader探遵,BufferedReader替代BufferedInputStream.對(duì)文件窟赏、網(wǎng)絡(luò)IO皆適用。
g.layout緩存
h. 其他需要頻繁訪問或訪問一次消耗較大的數(shù)據(jù)緩存
(2). 數(shù)據(jù)存儲(chǔ)優(yōu)化
包括數(shù)據(jù)類型箱季、數(shù)據(jù)結(jié)構(gòu)的選擇涯穷。
a. 數(shù)據(jù)類型選擇
字符串拼接用StringBuilder代替String,在非并發(fā)情況下用StringBuilder代替StringBuffer藏雏。如果你對(duì)字符串的長(zhǎng)度有大致了解拷况,如100字符左右,可以直接new StringBuilder(128)指定初始大小,減少空間不夠時(shí)的再次分配赚瘦。
64位類型如long double的處理比32位如int慢
使用SoftReference粟誓、WeakReference相對(duì)正常的強(qiáng)應(yīng)用來說更有利于系統(tǒng)垃圾回收
final類型存儲(chǔ)在常量區(qū)中讀取效率更高
LocalBroadcastManager代替普通BroadcastReceiver,效率和安全性都更高
b. 數(shù)據(jù)結(jié)構(gòu)選擇
常見的數(shù)據(jù)結(jié)構(gòu)選擇如:
ArrayList和LinkedList的選擇蚤告,ArrayList根據(jù)index取值更快努酸,LinkedList更占內(nèi)存、隨機(jī)插入刪除更快速杜恰、擴(kuò)容效率更高获诈。一般推薦ArrayList。
ArrayList心褐、HashMap舔涎、LinkedHashMap、HashSet的選擇逗爹,hash系列數(shù)據(jù)結(jié)構(gòu)查詢速度更優(yōu)亡嫌,ArrayList存儲(chǔ)有序元素,HashMap為鍵值對(duì)數(shù)據(jù)結(jié)構(gòu)掘而,LinkedHashMap可以記住加入次序的hashMap挟冠,HashSet不允許重復(fù)元素。
HashMap袍睡、WeakHashMap選擇知染,WeakHashMap中元素可在適當(dāng)時(shí)候被系統(tǒng)垃圾回收器自動(dòng)回收,所以適合在內(nèi)存緊張型中使用斑胜。
Collections.synchronizedMap和ConcurrentHashMap的選擇控淡,ConcurrentHashMap為細(xì)分鎖,鎖粒度更小止潘,并發(fā)性能更優(yōu)掺炭。Collections.synchronizedMap為對(duì)象鎖,自己添加函數(shù)進(jìn)行鎖控制更方便凭戴。
Android也提供了一些性能更優(yōu)的數(shù)據(jù)類型,如SparseArray簇宽、SparseBooleanArray勋篓、SparseIntArray、Pair魏割。
Sparse系列的數(shù)據(jù)結(jié)構(gòu)是為key為int情況的特殊處理譬嚣,采用二分查找及簡(jiǎn)單的數(shù)組存儲(chǔ),加上不需要泛型轉(zhuǎn)換的開銷钞它,相對(duì)Map來說性能更優(yōu)拜银。不過我不太明白為啥默認(rèn)的容量大小是10殊鞭,是做過數(shù)據(jù)統(tǒng)計(jì)嗎,還是說現(xiàn)在的內(nèi)存優(yōu)化不需要考慮這些東西尼桶,寫16會(huì)死嗎操灿,還是建議大家根據(jù)自己可能的容量設(shè)置初始值。
(3). 算法優(yōu)化
這個(gè)主題比較大泵督,需要具體問題具體分析迄埃,盡量不用O(n*n)時(shí)間復(fù)雜度以上的算法蜗帜,必要時(shí)候可用空間換時(shí)間。
查詢考慮hash和二分,盡量不用遞歸驹马∶湓酰可以從結(jié)構(gòu)之法 算法之道或微軟爆阶、Google等面試題學(xué)習(xí)沃测。
(4). JNI
Android應(yīng)用程序大都通過Java開發(fā),需要Dalvik的JIT編譯器將Java字節(jié)碼轉(zhuǎn)換成本地代碼運(yùn)行入问,而本地代碼可以直接由設(shè)備管理器直接執(zhí)行丹锹,節(jié)省了中間步驟,所以執(zhí)行速度更快芬失。不過需要注意從Java空間切換到本地空間需要開銷楣黍,同時(shí)JIT編譯器也能生成優(yōu)化的本地代碼,所以糟糕的本地代碼不一定性能更優(yōu)棱烂。
這個(gè)優(yōu)化點(diǎn)會(huì)在后面單獨(dú)用一片博客介紹锡凝。
(5). 邏輯優(yōu)化
這個(gè)不同于算法,主要是理清程序邏輯垢啼,減少不必要的操作。
(6). 需求優(yōu)化
這個(gè)就不說了张肾,對(duì)于sb的需求可能帶來的性能問題芭析,只能說做為一個(gè)合格的程序員不能只是執(zhí)行者,要學(xué)會(huì)說NO吞瞪。不過不能拿這種接口敷衍產(chǎn)品經(jīng)理哦馁启。
2、異步芍秆,利用多線程提高TPS
充分利用多核Cpu優(yōu)勢(shì)惯疙,利用線程解決密集型計(jì)算、IO妖啥、網(wǎng)絡(luò)等操作霉颠。
關(guān)于多線程可參考:Java線程池
在Android應(yīng)用程序中由于系統(tǒng)ANR的限制,將可能造成主線程超時(shí)操作放入另外的工作線程中荆虱。在工作線程中可以通過handler和主線程交互蒿偎。
3朽们、提前或延遲操作,錯(cuò)開時(shí)間段提高TPS
(1) 延遲操作
不在Activity诉位、Service骑脱、BroadcastReceiver的生命周期等對(duì)響應(yīng)時(shí)間敏感函數(shù)中執(zhí)行耗時(shí)操作,可適當(dāng)delay苍糠。
Java中延遲操作可使用ScheduledExecutorService叁丧,不推薦使用Timer.schedule;
Android中除了支持ScheduledExecutorService之外,還有一些delay操作岳瞭,如
handler.postDelayed拥娄,handler.postAtTime,handler.sendMessageDelayed寝优,View.postDelayed条舔,AlarmManager定時(shí)等。
(2) 提前操作
對(duì)于第一次調(diào)用較耗時(shí)操作乏矾,可統(tǒng)一放到初始化中孟抗,將耗時(shí)提前。如得到壁紙wallpaperManager.getDrawable();
4钻心、網(wǎng)絡(luò)優(yōu)化
更多見性能優(yōu)化第四篇——移動(dòng)網(wǎng)絡(luò)優(yōu)化
以下是網(wǎng)絡(luò)優(yōu)化中一些客戶端和服務(wù)器端需要盡量遵守的準(zhǔn)則:
a. 圖片必須緩存凄硼,最好根據(jù)機(jī)型做圖片做圖片適配
b. 所有http請(qǐng)求必須添加httptimeout
c. 開啟gzip壓縮
d. api接口數(shù)據(jù)以json格式返回,而不是xml或html
e. 根據(jù)http頭信息中的Cache-Control及expires域確定是否緩存請(qǐng)求結(jié)果捷沸。
f. 確定網(wǎng)絡(luò)請(qǐng)求的connection是否keep-alive
g. 減少網(wǎng)絡(luò)請(qǐng)求次數(shù)摊沉,服務(wù)器端適當(dāng)做請(qǐng)求合并。
h. 減少重定向次數(shù)
i. api接口服務(wù)器端響應(yīng)時(shí)間不超過100ms
google正在做將移動(dòng)端網(wǎng)頁速度降至1秒的項(xiàng)目痒给,關(guān)注中https://developers.google.com/speed/docs/insights/mobile