2013年4月27日 星期六

[Android] Google I/O Memory Leak 筆記 1 - 觀念

從 C/C++ 到 Android/Java Destructor 不見了! 但是對 Memory Leak 的擔憂並沒有消失, 反而是為 Android 時不時的 GC 而擔憂。 找了下面這 Google I/O Memory Leak 的演講, 看完可以建立很不錯的觀念。


Google I/O 2011: Memory management for Android Apps





===================================================
From Below My Own Notes
===================================================


這個演講的 Outline




To Know how much Heap you can use -    ActivityManager.getMemoryClass()

        



*HoneyComb 後新增可以加大允許Heap的功能 , 這個會增大 Heap, 增加 GC負擔, 會把其他APP 的 memory kick out, 所以要小心使用    *有些APP 非常需要 Memory, 所以如果要擴大一些 heap 在 AndroidManifest.xml 加 android:largeHeap = "true"  *AcitivityManager.getLargeMemoryClass() return  memory 可用的


-GC :
How it works -  從GC Roots 開始 visiting 其他 object by referencing.   沒被 reference 到的就被 GC collect






*Bigger heaps = longer pauses?
*Pre-Gingerbread GC: 
       stop- the-world collect - GC in progress 時 app是 stops 的
       Full heap collection 
       Pause time often > 100ms
*Gingerbread and beyond
    Concurrent (mostly) : when GC , app not stops
    Partial collections        : 通常有 one in begining , one in end
    Pause time usually < 5ms





-Bitmap  :
 Gingerbread/Honeycomb 之前
            See pic . 藍色是 Dalvik Heap, 綠色是 is bitmap. 
            Btimap 都是同樣的 size 不管 screen 的 resolution 為何。
            Bitmap 的 backing (?) Memory 是另存在另一個 Object 裡的。
            Pixels 也是存在其他地方。Pixels 的 memory 是使用 malloc 的方法在
           Dalvik Heap 之外取得。
            這個的問題是 - 
            1. Finalizer 是繼承一個不太穩定的 class並不是太可以信賴, 
            2. 因為 像 Pixel 這個是使用 Dalvik heap 外的 memory 所以不太好 Debug
            3. Stop the world process , 一 GC , APP 的 Process 就停止了
 Gingerbread/Honeycomb   之後
            在 APP Process 的同時也進行數次的 GC 
            Easier to debug 
            Concurrent & partial GCs







Reason for GC 

    *GC_CONCURRENT  
    Heap 快要滿時就會呼叫 GC_CONCURRENT  以防 Heap 滿了
     *GC_FOR_MALLOC
    假如上面的   GC_CONCURRENT  還沒完成但是APP 又需要 memory 時就會呼叫 
    GC_EXTERNAL_ALLOC
     需要 external memory allocation 的 Data , ie  Bitmap pixel (HoneyComb B4以前有) 
    GC_HPROF_DUMP_HEAP
    For HPROF File
    GC_EXPLICIT
    在 APP 呼叫 GC 時就會出現 GC_EXPLICIT, 不建議自己call system GC
    
    Log Messages 顯示依次為 
    Reason for GC   
    Amount freed    (free memory/total memory)
    Heap statistics 
    External memory statistics
    Pause time  (CONCURRENT有兩一個在 begining 一個在 end)

如何從 DMMS dump Memory (按DMMS 上的那個 icon)
Heap Dumps 
    Binary dump of all objects
    Create with 
        DDMS
        android.os.Debug.dumpHprofData()
        Convert to Standard HPROF format:  (Eclipse 會自動 convert)
         hprof -conv orig.hprof converted.hprof
    Analyze with MAT, jhat, etc


Leak 的產生通常是因為一直有 reference 到一個 unused 的 memory 所以 GC 無法清除它
比如常見的像 holding Context, 如果長時間 holding context 可能造成 GC 理由如下圖

一開始有一個 Activity, 但當Device 改變方向時, Android 會 create 一個全新的activity 然後指標指向新的Activity , 這時舊的 Activity 就應該被 GC 掉, 但因為別處 holding 舊的 context, 因為導致舊有的Activity 無法被清除掉


MAT 常用的兩個觀念
 Shallow heap  - how large is the object (size) 物件的Size
 Retained heap -  If  i want free this object ,  假如我GC這個物件, 
那麼指向這個物件的物件也可以被GC。 
這個 Retained heap 就是這個被GC 的總數
               



上面兩張圖再解釋 Retained Heap 
第一張圖, 如果黃色的 node 被清除, 它的 Retained size = 100 因為它被清除並不引響其他node
第二章圖, 如果黃色的 node 被清除, 它的 Retained size = 400 因為它被清除後, 其他 3 個 node 也可被 GC 所以 total 是 400 


所以這個清除的關係可以化成 Dominator Tree 的來看 
 Dominator Tree 定義是
 A is said to be the dominator of B  if every path goes to B , goes through A 
也就是說凡是到 B 的都會經過 A 那麼 A 就是 B 的 Dominator Tree
    
    Dominator Tree 左圖 原來的 轉成 右圖 Dominator Tree  
    B,C 只能由 A 經過 => A 是 BC 的 DT 
    E 只能由 C 經過  =>  C 是 E 的 DT 
    D 可由 BC 經過, 但依定都要由 A 經過 => A 是 D 的 DT


影片觀念的部分為上面的PPT , 接下來就是實作觀察 LogCat 與 MAT 的實作

最後補充資料

    
Memory Leaks
References to Activity,Context,View,Drawable (Don't hold it long)
Non-static inner class  (Runable)
Caches

Reference : 


http://speakermeter.com/talks/memory-management-android (!?)





沒有留言:

張貼留言