轉(zhuǎn)帖|行業(yè)資訊|編輯:蔣永|2016-09-19 11:04:52.000|閱讀 246 次
概述:Google近期在Udacity上發(fā)布了Android性能優(yōu)化的在線課程,分別從渲染,運(yùn)算與內(nèi)存,電量幾個(gè)方面介紹了如何去優(yōu)化性能,這些課程是Google之前在Youtube上發(fā)布的Android性能優(yōu)化典范專題課程的細(xì)化與補(bǔ)充。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
Google近期在Udacity上發(fā)布了Android性能優(yōu)化的在線課程,分別從渲染,運(yùn)算與內(nèi)存,電量幾個(gè)方面介紹了如何去優(yōu)化性能,這些課程是Google之前在Youtube上發(fā)布的Android性能優(yōu)化典范專題課程的細(xì)化與補(bǔ)充。
下面是內(nèi)存篇章的學(xué)習(xí)筆記,部分內(nèi)容與前面的性能優(yōu)化典范有重合,歡迎大家一起學(xué)習(xí)交流!
眾所周知,與C/C++需要通過手動(dòng)編碼來申請(qǐng)以及釋放內(nèi)存有所不同,Java擁有GC的機(jī)制。Android系統(tǒng)里面有一個(gè)Generational Heap Memory的模型,系統(tǒng)會(huì)根據(jù)內(nèi)存中不同的內(nèi)存數(shù)據(jù)類型分別執(zhí)行不同的GC操作。例如,最近剛分配的對(duì)象會(huì)放在Young Generation區(qū)域,這個(gè)區(qū)域的對(duì)象通常都是會(huì)快速被創(chuàng)建并且很快被銷毀回收的,同時(shí)這個(gè)區(qū)域的GC操作速度也是比Old Generation區(qū)域的GC操作速度更快的。
除了速度差異之外,執(zhí)行GC操作的時(shí)候,所有線程的任何操作都會(huì)需要暫停,等待GC操作完成之后,其他操作才能夠繼續(xù)運(yùn)行。
通常來說,單個(gè)的GC并不會(huì)占用太多時(shí)間,但是大量不停的GC操作則會(huì)顯著占用幀間隔時(shí)間(16ms)。如果在幀間隔時(shí)間里面做了過多的GC操作,那么自然其他類似計(jì)算,渲染等操作的可用時(shí)間就變得少了。
Android Studio中的Memory Monitor可以很好的幫助我們查看程序的內(nèi)存使用情況。
內(nèi)存泄漏表示的是不再用到的對(duì)象因?yàn)楸诲e(cuò)誤引用而無法進(jìn)行回收。
發(fā)生內(nèi)存泄漏會(huì)導(dǎo)致Memory Generation中的剩余可用Heap Size越來越小,這樣會(huì)導(dǎo)致頻繁觸發(fā)GC,更進(jìn)一步引起性能問題。
舉例內(nèi)存泄漏,下面init()方法來自某個(gè)自定義View:
private void init() { ListenerCollector collector = new ListenerCollector(); collector.setListener(this, mListener); }
上面的例子容易存在內(nèi)存泄漏,如果activity因?yàn)樵O(shè)備翻轉(zhuǎn)而重新創(chuàng)建,自定義的View會(huì)自動(dòng)重新把新創(chuàng)建出來的mListener給綁定到ListenerCollector中,但是當(dāng)activity被銷毀的時(shí)候,mListener卻無法被回收了。
下圖演示了Android Tools里面的Heap Viewer的功能,我們可以看到當(dāng)前進(jìn)程中的Heap Size的情況,分別有哪些類型的數(shù)據(jù),占比是多少。
Memory Churn內(nèi)存抖動(dòng),內(nèi)存抖動(dòng)是因?yàn)樵诙虝r(shí)間內(nèi)大量的對(duì)象被創(chuàng)建又馬上被釋放。瞬間產(chǎn)生大量的對(duì) 象會(huì)嚴(yán)重占用Young Generation的內(nèi)存區(qū)域,當(dāng)達(dá)到閥值,剩余空間不夠的時(shí)候,會(huì)觸發(fā)GC從而導(dǎo)致剛產(chǎn)生的對(duì)象又很快被回收。即使每次分配的對(duì)象占用了很少的內(nèi)存, 但是他們疊加在一起會(huì)增加Heap的壓力,從而觸發(fā)更多其他類型的GC。這個(gè)操作有可能會(huì)影響到幀率,并使得用戶感知到性能問題。
解決上面的問題有簡(jiǎn)潔直觀方法,如果你在Memory Monitor里面查看到短時(shí)間發(fā)生了多次內(nèi)存的漲跌,這意味著很有可能發(fā)生了內(nèi)存抖動(dòng)。
同時(shí)我們還可以通過Allocation Tracker來查看在短時(shí)間內(nèi),同一個(gè)棧中不斷進(jìn)出的相同對(duì)象。這是內(nèi)存抖動(dòng)的典型信號(hào)之一。
當(dāng)你大致定位問題之后,接下去的問題修復(fù)也就顯得相對(duì)直接簡(jiǎn)單了。例如,你需要避免在for循環(huán)里面分配對(duì)象占用內(nèi)存,需要嘗試把對(duì)象的創(chuàng)建移到循 環(huán)體之外,自定義View中的onDraw方法也需要引起注意,每次屏幕發(fā)生繪制以及動(dòng)畫執(zhí)行過程中,onDraw方法都會(huì)被調(diào)用到,避免在onDraw 方法里面執(zhí)行復(fù)雜的操作,避免創(chuàng)建對(duì)象。對(duì)于那些無法避免需要?jiǎng)?chuàng)建對(duì)象的情況,我們可以考慮對(duì)象池模型,通過對(duì)象池來解決頻繁創(chuàng)建與銷毀的問題,但是這里 需要注意結(jié)束使用之后,需要手動(dòng)釋放對(duì)象池中的對(duì)象。
關(guān)于Allocation Tracker工具的使用,不展開了,參考下面的鏈接:
下面演示一個(gè)例子,如何通過修改代碼來避免內(nèi)存抖動(dòng)。優(yōu)化之前的內(nèi)存檢測(cè)圖:
定位代碼之后,修復(fù)了String拼接的問題:
優(yōu)化之后的內(nèi)存監(jiān)測(cè)圖:
上面提到了三種測(cè)量?jī)?nèi)存的工具,下面再簡(jiǎn)要概括一下他們各自的特點(diǎn):
本文轉(zhuǎn)自()
>>查看更多關(guān)于移動(dòng)開發(fā)相關(guān)資訊<<
關(guān)于安卓開發(fā),您可能對(duì)這些產(chǎn)品感興趣
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn