Android内存解析<二>

来源:互联网 发布:空气净化器有用吗 知乎 编辑:程序博客网 时间:2024/05/19 19:44

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的管理做下整理,希望后续对自己有帮忙。

原创粉丝点击