Android内存分析

内存表达方式

  • VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
  • RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
  • PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
  • USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

我们在Android手机的设置页面看到的内存占用情况,就是使用了PSS标准。同时在内存优化过程中,也经常被用作衡量指标。

PSS内存查看方式

  • adb shell dumpsys meminfo
  • 手写测试程序:
    • activitymanager.getRunningAppProcesses():
    • memoryinfo[0].getTotalPss():

dumpsys meminfo详述

Android内存分析_第1张图片
dumpsys-meminfo.png

接下来,我们对上图中的信息做详细说明:

  • Dalvik Heap
    在app中由Dalvik申请的内存。
    Pss Total包含了Zygote申请的内存(只不过Pss是按照共享数均分给每个进程)。

这里做下说明,android下所有app的进程均是fork自Zygote,从Zygote进程 fork 时,子进程完全拷贝了Zygote进程的虚拟内存空间(包括加载的so占用、resource资源占用、主动申请等内存空间等)。但当继承自Zygote进程的内存被修改时,由于copy-on-write,会申请新的内存空间,这就会形成Private Dirty内存。当继承自Zygote进程的内存没被修改时,是不用分配额外的内存空间。

  • Private Dirty
    它是app自己提交的内存总数,包含了app自己主动申请的和修改了的继承自Zygote的内存。
    其实,Private Dirty表示了该进程私有的,不跟disk数据一致的内存段。例如堆(heap),栈(stack),bss段。

    注:在新平台上,用于管理Dalvik的内存(如, just-in-time compilation (JIT) and GC bookkeeping)不再像以前一样归到 Dalvik Heap,而是归类到 Dalvik Other。

  • Heap Size/Alloc/Free
    Heap Alloc是(Dalvik、native)app申请的内存记录,包括了Private Dirty和继承自Zygote的(多进程共享的)内存。所以,它是比Pss Total和Private Dirty都要大的。

  • Private clean
    它包括该进程独自使用的so和dex。Clean内存的好处是在内存紧张时,可以释放物理内存。因为是clean的,所以不需要写回到disk,只需要下次读取该内存(导致缺页错误)时再从disk读入。

  • Shared Clean
    它表示多个进程共享的so和dex。关于so库的加载,第一次是以MAP_PRIVATE参数 mmap so,内存都是private clean的。如果另外一个进程mmap了同一个so,就变成shared clean了。

DDMS:MemoryMonitor

Android自带的内存查看工具,查看的是Dalivik Heap Size/Alloc/Free。

内存优化工具:MAT

强大的内存分析工具,MAT,分析的文件hprof文件有以下获取方式(都需要使用hprof-conv工具转换):

  • DDMS 中dump出来
  • 函数:dumpHprofData()生成

使用MAT分析内存时,会遇到一些术语比较难懂的术语,这里简单说明下:

  • RetainedHeap:
    它表示如果一个对象被释放掉,那会因为该对象的释放而减少引用进而被释放的所有的对象(包括被递归释放的)所占用的heap大小。(又开始Histogram中不显示Retained heap,需要点击那个计算器的按钮才会计算出来)。这里最小的粒度是类级别的。

  • Dominator Tree:
    它表示对象引用树(原来是用图表示对象引用关系)。

  • MAT中点击右键

    • 在List objects中选择with outgoing references和with incoming references。这是个真正的引用图的概念,表示该对象的出节点(被该对象引用的对象)和入节点(引用到该对象的对象)。
    • Path to GC Roots:GC roots是可能导致GC的节点。这个Path则是从这些GC root节点中的某个到当前对象的最短引用路径。对这个如何计算不是很确定,我想应该是根据引用树而不是dominator tree。

参考:
https://developer.android.com/studio/profile/investigate-ram.html#LogMessages
https://www.youtube.com/watch?v=ptjedOZEXPM

你可能感兴趣的:(Android内存分析)