內(nèi)存表達(dá)方式
- VSS- Virtual Set Size 虛擬耗用內(nèi)存(包含共享庫占用的內(nèi)存)
- RSS- Resident Set Size 實(shí)際使用物理內(nèi)存(包含共享庫占用的內(nèi)存)
- PSS- Proportional Set Size 實(shí)際使用的物理內(nèi)存(比例分配共享庫占用的內(nèi)存)
- USS- Unique Set Size 進(jìn)程獨(dú)自占用的物理內(nèi)存(不包含共享庫占用的內(nèi)存)
我們在Android手機(jī)的設(shè)置頁面看到的內(nèi)存占用情況羔味,就是使用了PSS標(biāo)準(zhǔn)捐凭。同時在內(nèi)存優(yōu)化過程中娃惯,也經(jīng)常被用作衡量指標(biāo)。
PSS內(nèi)存查看方式
- adb shell dumpsys meminfo
- 手寫測試程序:
- activitymanager.getRunningAppProcesses():
- memoryinfo[0].getTotalPss():
dumpsys meminfo詳述
接下來茧吊,我們對上圖中的信息做詳細(xì)說明:
-
Dalvik Heap
在app中由Dalvik申請的內(nèi)存竹挡。
Pss Total包含了Zygote申請的內(nèi)存(只不過Pss是按照共享數(shù)均分給每個進(jìn)程)液兽。
這里做下說明庶弃,android下所有app的進(jìn)程均是fork自Zygote,從Zygote進(jìn)程 fork 時尺碰,子進(jìn)程完全拷貝了Zygote進(jìn)程的虛擬內(nèi)存空間(包括加載的so占用挣棕、resource資源占用、主動申請等內(nèi)存空間等)亲桥。但當(dāng)繼承自Zygote進(jìn)程的內(nèi)存被修改時洛心,由于copy-on-write,會申請新的內(nèi)存空間题篷,這就會形成Private Dirty內(nèi)存词身。當(dāng)繼承自Zygote進(jìn)程的內(nèi)存沒被修改時,是不用分配額外的內(nèi)存空間番枚。
-
Private Dirty
它是app自己提交的內(nèi)存總數(shù)法严,包含了app自己主動申請的和修改了的繼承自Zygote的內(nèi)存。
其實(shí)葫笼,Private Dirty表示了該進(jìn)程私有的深啤,不跟disk數(shù)據(jù)一致的內(nèi)存段施戴。例如堆(heap)厂抖,棧(stack),bss段帘瞭。注:在新平臺上,用于管理Dalvik的內(nèi)存(如呈昔, just-in-time compilation (JIT) and GC bookkeeping)不再像以前一樣歸到 Dalvik Heap挥等,而是歸類到 Dalvik Other。
Heap Size/Alloc/Free
Heap Alloc是(Dalvik堤尾、native)app申請的內(nèi)存記錄肝劲,包括了Private Dirty和繼承自Zygote的(多進(jìn)程共享的)內(nèi)存。所以哀峻,它是比Pss Total和Private Dirty都要大的涡相。Private clean
它包括該進(jìn)程獨(dú)自使用的so和dex哲泊。Clean內(nèi)存的好處是在內(nèi)存緊張時剩蟀,可以釋放物理內(nèi)存。因為是clean的切威,所以不需要寫回到disk育特,只需要下次讀取該內(nèi)存(導(dǎo)致缺頁錯誤)時再從disk讀入。Shared Clean
它表示多個進(jìn)程共享的so和dex先朦。關(guān)于so庫的加載缰冤,第一次是以MAP_PRIVATE參數(shù) mmap so,內(nèi)存都是private clean的喳魏。如果另外一個進(jìn)程mmap了同一個so棉浸,就變成shared clean了。
DDMS:MemoryMonitor
Android自帶的內(nèi)存查看工具刺彩,查看的是Dalivik Heap Size/Alloc/Free迷郑。
內(nèi)存優(yōu)化工具:MAT
強(qiáng)大的內(nèi)存分析工具,MAT创倔,分析的文件hprof文件有以下獲取方式(都需要使用hprof-conv工具轉(zhuǎn)換):
- DDMS 中dump出來
- 函數(shù):dumpHprofData()生成
使用MAT分析內(nèi)存時嗡害,會遇到一些術(shù)語比較難懂的術(shù)語,這里簡單說明下:
RetainedHeap:
它表示如果一個對象被釋放掉畦攘,那會因為該對象的釋放而減少引用進(jìn)而被釋放的所有的對象(包括被遞歸釋放的)所占用的heap大小霸妹。(又開始Histogram中不顯示Retained heap,需要點(diǎn)擊那個計算器的按鈕才會計算出來)知押。這里最小的粒度是類級別的叹螟。Dominator Tree:
它表示對象引用樹(原來是用圖表示對象引用關(guān)系)。-
MAT中點(diǎn)擊右鍵
- 在List objects中選擇with outgoing references和with incoming references台盯。這是個真正的引用圖的概念首妖,表示該對象的出節(jié)點(diǎn)(被該對象引用的對象)和入節(jié)點(diǎn)(引用到該對象的對象)。
- Path to GC Roots:GC roots是可能導(dǎo)致GC的節(jié)點(diǎn)爷恳。這個Path則是從這些GC root節(jié)點(diǎn)中的某個到當(dāng)前對象的最短引用路徑有缆。對這個如何計算不是很確定,我想應(yīng)該是根據(jù)引用樹而不是dominator tree。
參考:
https://developer.android.com/studio/profile/investigate-ram.html#LogMessages
https://www.youtube.com/watch?v=ptjedOZEXPM