1. 程式人生 > >App性能測試前需要了解的內存原理

App性能測試前需要了解的內存原理

通過 退出 性能測試 沒有 androi 分代 prop 級別 ber

這兩天在研究性能中內存方面的一塊,網上也零散看了挺多文章,寫得很細但是感覺不夠整體,所以這篇算是總結一下吧,當個復習資料。
那麽這裏個人分為兩個大部分,第一部分應用內的內存管理,主要是oom的理解,GC機制和內存泄露這三個小部分;另一部分是系統級別的內存管理,包括內存共享,進程創建到LMK也就是消亡的一個簡要了解,具體到某個細節,網上挺多的,就不細說了,後續看心情再補寫⑧!

應用內的內存管理

一)為什麽會發生OOM

Android系統為每一個運行的程序都指定了一個最大運行內存,超過這個值則會觸發OOM機制,反應在界面就是閃退、crash現象,導致OOM發生的原因比如內存泄露或者是代碼不考慮後果使用大量的資源,都有可能導致OOM出現的。OOM的臨界值可以通過adb shell getprop | grep ‘heap’查看到
技術分享圖片


比如這裏,heapgrowthlimit是默認單個app最大內存,heapsize則是manifest文件裏設置android:largeHeap=”true”,則會使用這個最大值。

二)android裏的GC機制

GC機制沿用了java的GC機制,當需要新內存去分配對象的時候而剩余不夠的時候,會觸發GC,把無用的對象回收掉,其中一個重要的算法便是分代式算法,這個算法把虛擬機分為年輕代、老年代和持久代,對象先分配到年輕代,然後GC多次後還存活的將會移動到老年代,老年代就不會頻繁觸發GC機制,一般觸發頻繁的都是年輕代的對象。

三)為什麽會內存泄露

第二點我們知道了GC機制,那麽如果GC過後程序還是沒有內存,那麽會發生OOM,導致GC後還是沒有足夠內存分配新對象的主要原因就是內存泄露了。首先要知道內存泄露也就是GC不掉的根源是生命周期長的對象持有生命周期短的對象,導致無用的對象一直無法回收。下面來看看幾個典型的分類:

**靜態類相關的泄露:**static對象的生命周期伴隨著整個程序的生命周期,所以這塊要註意不要把一些對象引用添加到static對象裏面去,會造成與之關聯的對象無法回收。

各種資源的釋放:很多了,包括cursor的關閉,IO流的關閉,bitmap的回收等等,進行一些帶有緩存的資源一定要關閉或者釋放。

Handler的泄露:調用handler的delay的時候,會被認為對象是有用的,導致無法回收,還有handler開啟線程去下載東西沒有下載完成的時候,也會因為線程導致無法回收activity;或者使用handlerThread的時候,有延遲的方法,都會導致無法回收。其主要原因在於handler是持有activity的引用,你看主線程不是自帶一個Looper然後給handler用嘛,導致有關聯關系。

各種註冊引用方法:比如一個常駐的後臺線程處理某些時間,把當前對象註冊,因為一直持有對象引用,導致這個activity一直保留,所以不用的時候需要反註冊。

把對象緩存進容器內卻忘記remove掉:有時候為了加快頁面響應,結果緩存一些對象到容器內,結果越加越多,然後掛掉,網上有這個例子,雖然我暫時還沒碰到,一塊寫了。

系統級別的內存管理

一) zygote的內存共享

我們知道我們的應用進程都是由zygote fork()出來的,包括系統服務和用戶程序。這塊的內存共享主要共享的是通用的資源內存,比如自帶的主題樣式,這樣就避免了浪費內存空間讀取一樣的資源了。

二)LMK機制和oom_adj的值

Android內核有個專用的驅動low-memory-kill,當系統級別的內存不夠的時候會根據oom_adj的值以及內存分配狀況去kill掉某個進程,oom_adj可以在/proc/[pid]/oom_adj看到,並且這個值會隨著進程的狀態改變而改變,比如系統進程一般是-16,越大越容易被幹掉

三) 5個進程的優先級

前臺進程:當前運行的,基本不死
可見進程:界面可以見到,比如被遮擋
服務進程:進程帶後臺服務的,比如播放器
後臺進程:點擊home鍵,但不退出,就是後臺進程了,有比較大幾率會被殺
空進程:退出應用程序,還在後臺保留這空進程,為的是加快啟動速率,最優先殺的對象

四) 共享內存

安卓的內存的管理是分頁和內存映射的,一個android程序運行的時候,會把虛擬內存通過內存映射的方式給到運行的進程,當真正要執行這塊內容的時候,會通過分頁的當時去分配實際內存,那麽虛擬內存包括什麽東西呢?
在linux環境下,通過命令

pmap -x [pid]
  • 1

可以查詢虛擬內存空間實例
技術分享圖片
技術分享圖片
可以看到虛擬內存的空間主要是包括這些的,代碼段,堆棧,匿名共享內存,動態鏈接庫等等。
這裏又出現了一個名詞,匿名共享內存,實際上這是系統開辟一個內存空間,然後映射到進程的虛擬空間,可以實現多進程共享,比如android的顯示過程,處理好的surface交給surfaceFlinger服務,服務則是通過匿名共享內存的方式給緩沖區再進一步繪制我們看到的圖像。
好了,總結一下,android涉及的共享內存,一個是zygote生出的子代,共享android的一些資源,一些類庫,一些數據。第二個是匿名共享內存,包括surface,圖形驅動音頻驅動等等。

轉至:http://blog.csdn.net/Cloud_Huan/article/details/51146103

App性能測試前需要了解的內存原理