内存测试入门
1.1新手入門
當(dāng)軟件實(shí)現(xiàn)了新功能后,準(zhǔn)備發(fā)布版本前,往往需要進(jìn)行一輪性能測試以確定沒有性能問題,這類測試通常包括功能的流暢度,電量消耗和內(nèi)存使用情況等。
由于內(nèi)存組成的復(fù)雜性,實(shí)際上并沒有簡單通用的方法就能夠發(fā)現(xiàn)所有的內(nèi)存問題。下面的章節(jié)里,我們會(huì)圍繞一組案例展開,通過對(duì)案例的分析講解各種內(nèi)存測試的工具和方法。這些例子都是從真實(shí)的測試案例中提取的,經(jīng)過加工后使得問題表現(xiàn)的更加明顯。
接下來我們以一個(gè)最常見的內(nèi)存泄漏開始,作為最典型的內(nèi)存問題,類似的情況可能在無數(shù)應(yīng)用的無數(shù)版本中出現(xiàn)過,而且還會(huì)不斷的在新版本里出現(xiàn)。對(duì)于這樣的問題,我們必須要準(zhǔn)確識(shí)別出來。
在大部分應(yīng)用中,經(jīng)常會(huì)有一類功能是需要加載附加資源的,比如顯示從網(wǎng)絡(luò)下載的文本或圖片。這類功能往往需要在內(nèi)存中存放要使用的資源對(duì)象,退出該功能后,就需要將這些資源對(duì)象清空。如果忘了清理,或者是代碼原因造成的清理無效,就會(huì)形成內(nèi)存泄漏。我們的測試任務(wù)就是保證功能的正常,并且不會(huì)有遺留的內(nèi)存對(duì)象造成泄漏。
要開始進(jìn)行性能測試,測試工具是必不可少的。我們一般都會(huì)優(yōu)先使用SDK/IDE自帶的工具,因此首先會(huì)想到的工具就是和IDE集成在一起的Android Device Monitor/Android Studio了。
大多數(shù)情況下,功能代碼都是由Dalvik虛擬機(jī)里執(zhí)行的Java代碼實(shí)現(xiàn)的,因此主要的內(nèi)存消耗也是由Java代碼使用new分配的內(nèi)存。Android Device Monitor和Android Studio能夠方便的觀察Heap Alloc部分的大小,進(jìn)行初步的統(tǒng)計(jì),還能夠觀察到GC發(fā)生時(shí)的內(nèi)存變化情況。
圖1-1 使用DDMS觀察應(yīng)用的內(nèi)存消耗 圖1-2 使用Android Studio觀察應(yīng)用的內(nèi)存消耗在圖1-1中,我們能夠看到應(yīng)用當(dāng)前消耗了多少內(nèi)存,以及各種不同類型對(duì)象的初步統(tǒng)計(jì)。在圖1-2中,Android Studio更進(jìn)一步的將內(nèi)存數(shù)據(jù)進(jìn)行了圖形化,這樣就能過方便地看出GC(垃圾回收)情況和明顯的內(nèi)存趨勢。如果存在明顯的內(nèi)存泄漏,那么在圖中就會(huì)表現(xiàn)為隨著功能的反復(fù)使用,內(nèi)存值不斷的升高,即使出現(xiàn)GC也沒法降下來,如圖1-3所示。
圖1-3典型的內(nèi)存泄漏發(fā)現(xiàn)了內(nèi)存泄漏,通常就可以交給開發(fā)去處理了。但我們能做的并不只是丟一個(gè)問題描述和復(fù)現(xiàn)路徑過去,而是利用手頭的工具,獲得一些更詳細(xì)的數(shù)據(jù),能夠使大家更快的定位和解決問題。這樣分析內(nèi)存獲得詳細(xì)數(shù)據(jù)的首選工具就是Eclipse Memory Analyzer(MAT)了。
1.1.1使用Eclipse Memory Analyzer(MAT)進(jìn)行內(nèi)存分析
Eclipse Memory Analyzer(MAT)是使用非常廣泛的Java內(nèi)存分析工具,功能強(qiáng)大。已經(jīng)有很多關(guān)于它的詳細(xì)教程,在本書中就不再細(xì)述用法。本節(jié)內(nèi)容主要介紹使用MAT在分析Android應(yīng)用時(shí)的一些常用技巧。
通常我們用MAT打開hprof文件后,能夠在首頁看到Top Consumers和Component Report等功能,使用這些功能能夠快速定位一些大塊的內(nèi)存消耗。但對(duì)于Android應(yīng)用的hprof文件,我們?cè)谑褂昧薚op Consumers統(tǒng)計(jì)使用情況后,往往只能看到如圖1-4所示的情況:
圖1-4 使用MAT分析內(nèi)存構(gòu)成
系統(tǒng)的資源類占據(jù)了很大一部分的內(nèi)存,而其余的前幾名也往往是系統(tǒng)類。這是由于從虛擬機(jī)角度不會(huì)區(qū)分系統(tǒng)框架和應(yīng)用自身的對(duì)象,后面的1.4.3節(jié)會(huì)詳細(xì)說明出現(xiàn)這種現(xiàn)象的原因。
為了去除這部分對(duì)分析的干擾,我們?cè)谟肁ndroid SDK提供的hprof-conv轉(zhuǎn)換時(shí)需要增加一個(gè)參數(shù):
hprof-conv [-z] <infile><outfile>-z: exclude non-app heaps, such as Zygote另一種可替代的方法是使用OQL。如果hprof文件是已經(jīng)轉(zhuǎn)換過的,可以在數(shù)據(jù)中尋找應(yīng)用的Application類對(duì)象,將對(duì)象地址轉(zhuǎn)換為10進(jìn)制后輸入以下查詢語句:
select * from instanceof java.lang.Object s where s.@objectAddress > 1107296256使用-z參數(shù)轉(zhuǎn)換或OQL查詢后得到的對(duì)象集合就只包含應(yīng)用代碼分配的部分了。在此基礎(chǔ)上使用MAT提供的Top Consumers和Component Report等功能就能夠得到比較準(zhǔn)確的結(jié)果。如圖1-5所示,沒有了系統(tǒng)類所占內(nèi)存的干擾,只有應(yīng)用自身代碼創(chuàng)建的對(duì)象,對(duì)于發(fā)現(xiàn)內(nèi)存問題比較有幫助。
圖1-5分離之后再次分析內(nèi)存構(gòu)成對(duì)于一般的內(nèi)存泄露類問題,使用以上方法后通過MAT提供的分析報(bào)告就很容易就會(huì)識(shí)別出來。在我們以往的測試經(jīng)歷中,用這種方法發(fā)現(xiàn)了上百次的內(nèi)存問題。這些內(nèi)存往往是加載后忘了釋放的Bitmap,臨時(shí)生成的byte數(shù)組和文件緩沖區(qū),包含Handler的Activity等等。
接下來我們看一個(gè)真實(shí)的應(yīng)用測試案例。在這個(gè)案例里,有些位圖在使用完之后由于種種原因,一直沒有銷毀而存在ImageLoader里,使用一段時(shí)間后ImageLoader會(huì)變得越來越龐大。使用上面介紹的方法去除了系統(tǒng)的影響后,MAT的泄露報(bào)告給出了結(jié)果,如圖1-6所示,ImageLoader消耗了接近1/3的內(nèi)存。
圖1-6 MAT識(shí)別出來的問題有了這樣的數(shù)據(jù),接下來就可以結(jié)合圖片追蹤代碼,看引用到ImageLoader的代碼部分哪里有問題,從而快速的修復(fù)問題。
注:轉(zhuǎn)載自騰訊Bugly
總結(jié)
- 上一篇: 如何在Win10下安装MySQL 5.7
- 下一篇: 网络压线钳的实验报告_RJ45网线制作实