Android內存解析

Android進程Memory分析

前一篇總結中,我從整體上對Android平臺各個模塊Memory的使用狀況進行了分析整理。這一篇,我再從Process的角度來分析單個進程的Memory使用狀況。
Process Memory過大對我們是不利的,一方面資深用戶如果發覺使用的App特別喫內存,則有被卸載的風險。另一方面App memory用量過大,當處於後臺時會成爲Low memory killer優先kill的的對象,導致用戶再次回到你的App時用戶體驗會降低。因此,優化應用的memory還是值得關注的一個方向。

1. Process Memory基礎

Android進程分爲兩種類型,一種是java process, 另外一種是純粹的c/c++的native process。Java process運行在DVM之上,所以每個process中都會帶有一個虛擬機。我們後面會看到java process所佔用的memory整體會比native process大。(關於Java process memory管理的部分我後續再總結)

1.1. 虛擬地址空間

無論是java process還是native process, 站在linux process的角度來看,其線性地址空間是的一樣的。我們先回顧下32位系統中進程memory的虛擬地址空間如下:

這裏寫圖片描述

1.2 虛擬地址到物理地址
先介紹幾個非常重要的概念,後續process內存分析都是在圍繞其中的幾個概念在做文章。

VSS : process佔用的虛擬內存的大小
RSS:process實際佔有的物理內存的大小,包括了與其他process共享的.so的內存
PSS:共享內存與其他process進行平攤後,該process實際佔有的物理內存的大小
USS:process私有佔用物理內存的大小,不包含共享庫的內存

怎麼理解上面這些概念呢?前面已經說明了process的虛擬地址空間,VSS就是在虛擬地址空間佔用的memory, 比如malloc一塊memory, 則虛擬空間中便宣稱了一片內存空間;如果我們沒有使用這塊memory, 則process僅僅是在虛擬空間有了這塊memory, 並沒有分配到實際的物理空間,只有在訪問這塊memory時由於產生缺頁中斷纔會真正的分配物理內存。RSS對應的也就是process中已經分配了的實際物理內存的大小。
給出一個簡單的虛擬內存到物理內存的映射示意圖如下:
A2和B2表示process A& Process B中使用了同一個共享庫,因此在物理內存中對應了同一塊區域。
process A對應的VSS大小是:A1 + A2 + A3
process A對應的RSS大小是:A1 + A2
process A對應的PSS大小是:A1 + A2/2
process A對應的USS大小是:A1

這裏寫圖片描述

2. 查看所有Process的Memory狀況
一般Android平臺或者設備的廠家會關注當前系統中有哪些Process在運行,每個Process的Memory用量大致如何。往往會抓住Memory用量非常大的進程,看看是否異常以及是否有進一步優化的空間。

查看所有process memory狀況的方式很多,我記錄幾種比較常見的方式:

2.1. adb shell ps
這種方式可以看到所有process的VSS以及RSS信息,而且user load上也可以使用。缺點是沒有按size 排序,可以自己使用excel table按RSS的值再排序後進行分析。

這裏寫圖片描述

2.2. adb shell procrank

這種方式缺點是在user load上不能抓到信息,只有各生產商內部RD們在eng的版本上才能分析。優點是各process的memory信息很清晰, 按PSS的大小進行了排序,可以很方便得關注到memory用量大的process以及你所關注的process的memory用量的排位狀況。

這裏寫圖片描述

2.3. adb shell dumpsys meminfo

這種方式與procrank一樣可以看到PSS的信息,而且還可以根據Adj的分類來查看Memory. 比如你需要關注所有persistent process的memory狀況,則可以很方面的從這裏得到結果。

這裏寫圖片描述

這裏寫圖片描述

3. 深入分析單個Process的Memory狀況
前面的一些command可以一次性把所有process的memory信息抓出來,從中我們可以初步的看到單個Process的memory信息,例如PSS, RSS等。如果想再深入看到更多詳細的信息,我們可以使用如下一些方法。

3.1. dumpsys meminfo pid

通過這種方式我們可以瞭解到PSS各個部分的大小。另外Private Dirty基本上是RW的部分,Private clean則是RO的部分,從這些信息中,我們可以基本瞭解到一個Process的Memory大致佔用狀況。

這裏寫圖片描述

3.2. cat /proc/pid/maps & cat /proc/pid/smaps

smaps則是更詳細的分析手段,不過這種方式在user load下不能抓到信息,只有平臺或者設備廠家的工程師們在eng load上才能一睹其芳容。
Linux中使用vm_area_struct來表示process的每一塊虛擬memory,而smaps正是所有vm_area_struct的信息的彙總,是對Process虛擬空間中每塊內存的詳細描述。
我從網上copy了一張圖過來進行說明,這裏只是截取了smaps種某一段memory的描述:

這裏寫圖片描述

第一行的各個字段整體描述了這一塊內存的信息:

  • 虛擬內存的起始地址
  • 這塊內存的屬性:可讀?可寫?可執行?是否私有?
  • 偏移地址
  • 最後一項信息則說明了這段內存所屬文件

    另外詳細信息中的,

  • size則是這一塊虛擬內存的大小
  • RSS和PSS則表明了這一塊虛擬內存在物理內存中實際映射佔有的空間

    如果對smaps更進一步分析,可以對vm的各段進行歸類彙總:根據第一行的最後一項信息區分出該虛擬內存段是屬於.so? stack? java heap?native heap?等等,這裏我不再進行記錄。

4. Process Heap分析
前面對process memory的分析基本上還是從整體上做分析,可以讓process的開發者從整體上了解process運行時會佔用多少的物理內存,或者更detail的瞭解到RO, RW, Heap等佔用memory的狀況。
對於Android App的開發者們更關注的是其中Heap的使用狀況。這部分的工具也比較多,我總結兩種分析的tool, 一種是Android Studio整合的Memory monitor,另一種介紹比較強大的MAT工具。

4.1. Android Monitor

Android Monitor的使用可以參考官網上的介紹,操作App的同時可以動態的觀察Heap的變化。
https://developer.android.google.cn/studio/profile/investigate-ram.html#HeapDump

這裏寫圖片描述

4.2. MAT (Memory Analyze Tool)

使用MAT之前,首先需要把Heap dump出來,方式比較多,例如DDMS的dump heap, 或者Android Studio中也可以dump heap, 或者使用adb shell am dumpheap命令也可以。例如我這邊使用了Android Studio裏面集成的dump heap功能:

這裏寫圖片描述

把Heap file dump出來後,需要使用SDK中帶的工具hprof-conv進行轉換:hprof-conv heap-original.hprof heap-converted.hprof

這裏寫圖片描述

最後使用MAT打開轉換後的hprof文件,可以看到對應Process的Heap信息:最外面的餅圖描述了Heap整體的大小,以及佔用Memory比較大的一些對象。
這裏寫圖片描述

或許你這裏會有疑問,怎麼上面看到的一個簡單的Hello World的程序Heap會如此之大呢? 這是因爲Android Java層的Process都是從Zygote fork出來的,所以每個Process都帶有zygote相對應的Memory信息,導致Heap會非常大。但實際上App本身私自分配使用的Heap會小很多,我們可以在hprof-conv時加上-z 參數來得到相關的信息:hprof-conv -z heap-original.hprof heap-converted.hprof

這裏寫圖片描述

這樣再用MAT打開新的hprof文件,會發現Heap小了很多:

這裏寫圖片描述

一般在分析Heap時,我們可以從dominator tree中進行分析,從Retained Heap一列可以看到各個對象佔用Memory的狀況。這樣可以有針對性的對特別大的對象考慮是否有優化的空間。

這裏寫圖片描述

如果你發現某些對象有異常,例如出現了泄漏沒有被釋放等,可以使用Path To GC Roots或者merge Shortest Paths to GC Roots來查看此對象被引用的路徑。

這裏寫圖片描述

這一篇總結從整體上對Android Process的Memory狀況進行了分析,從中可以瞭解一個process RO, RW等細分類型的memory用量,另外對App開發特別關注的Heap總結了分析方法。下一篇我準備對Dalvik虛擬機對Java process memory的管理做下整理,希望後續對自己有幫忙。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章