android 内存消耗分析

1、如何查看memory 的总消耗

linux的命令top -h 以及PS 都可以查看到内存PSS和VSS的内存消耗。android提供了工具,可以更全面的分析到内存的分布情况。先看procrank,这个工具没有,可以通过下载编译放在android /system/xbin/目录下。然后分别执行:
adb root
adb shell procrank
我们看一下内存分布结果:

 PID       Vss      Rss      Pss      Uss     Swap    PSwap    USwap    ZSwap  cmdline
 1012  1552016K  214564K  131199K  120700K   25304K   20554K   20356K   10391K  xxx.xxxx.xxx(进程名)

我们发现一个关系,VSS>RSS>PSS>USS(实际都是>=),那他们有什么区别呢?为什么存在大小差别。
首先是VSS,Virtual Set Size,也就是虚拟耗用内存,它包含了所有的分配的内存,这部分内存有可能还未使用。所以称为虚拟。除了包含本进程的分配内存,它还包含了共享库的内存。
RSS,Resident Set Size ,实际使用物理内存,因此他只包含了使用的内存,他除了包含自己使用的内存,还包含了所有的共享库的内存。
PSS,Proportional Set Size,实际使用物理内存,上面RSS讲到,会将所有的共享库的内存都算进来,如果很多程序都在使用共享库的内存,会造成全算到一个进程RSS里面,显然是不准确的,PSS则将共享库内存进行平均,算到每一个使用其的PSS内存里。
Uss,Unique Set Size ,进程独自占用内存,顾名思义,就是剥离了共享库的内存值。这个能更精确的反应当前进程本身的内存使用状况。

注:共享的内存怎么理解,比如调用很多公有服务,使用公有的库,这部分库的内存实际只会载入一次,所以这部分的内存归属问题,才有了现在这么多分组。

2、如何查看应用具体内存情况

这个就是我们常用的adb shell dumpsys meminfo xxxx(进程名)。
为什么我们这边一定强调一定是进程名,因为linux的内存页分配都是以进程为单位的,虽然默认情况下单进程的app,进程名就是app的包名。但是必须要强调。
我们看一个结果:

Applications Memory Usage (in Kilobytes):
Uptime: 3168126 Realtime: 3168126

** MEMINFO in pid 1012 [XXX.XXX.XXX(进程名)] **
                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    27293    27056      196     3695    38144    30571     7572
  Dalvik Heap    12776    12416      336     1993    18601    12473     6128
 Dalvik Other     1737     1736        0        2                           
        Stack       36       36        0        0                           
       Ashmem     4390     4372        0        0                           
    Other dev       30        4       20        0                           
     .so mmap    13517     6220     2684     2625                           
    .apk mmap     4083       72     2668     6316                           
    .ttf mmap      510        0      452        0                           
    .dex mmap    53489    24080    26868     6232                           
    .oat mmap     2094        0      532        0                           
    .art mmap     5876     5264      216       12                           
   Other mmap     6507        4     6220        0                           
   EGL mtrack    28021    28021        0        0                           
    GL mtrack    26319    26319        0        0                           
      Unknown     2448     2380       68      415                           
        TOTAL   210416   137980    40260    21290    56745    43044    13700
 
 App Summary
                       Pss(KB)
                        ------
           Java Heap:    17896
         Native Heap:    27056
                Code:    63576
               Stack:       36
            Graphics:    54340
       Private Other:    15336
              System:    32176
 
               TOTAL:   210416       TOTAL SWAP PSS:    21290
 
 Objects
               Views:      681         ViewRootImpl:        3
         AppContexts:        7           Activities:        1
              Assets:        5        AssetManagers:        3
       Local Binders:      151        Proxy Binders:       53
       Parcel memory:       30         Parcel count:      121
    Death Recipients:        2      OpenSSL Sockets:        5
            WebViews:        0
 
 SQL
         MEMORY_USED:     1105
  PAGECACHE_OVERFLOW:      822          MALLOC_SIZE:      117

可以看到这块内存主要字段有pss,private。我们从上往下看。
pss total,就对应我们上一节中提到的pss,它包含了应用自己的内存,还包含了共享(或跨进程)使用的内存。
相应的private dirty就表示,就是独自占用的脏页的内存值,脏页在linux里就表示高速缓存(在物理内存中)中被修改的内存页。相反private clean就表示高速缓存中未被修改的页。
swap内存,因为内存缓存机制,会基于最近最少使用的缓存原则,将内存中长时间不运行的数据,缓存到硬盘中,这部分数据到了硬盘中,swap之后的这部分内存称为虚拟内存,在需要使用的时候,才会从硬盘中读取出来。
所以实际上,我们就把private相关的值就表示应用本身的内存占用情况,相应的pss则增加了共享库内存的内存使用。

除了这块内存参数以外,还有heap size、heap alloc 和 heap free。
heap alloc表示我们在分配的内存大小,heap free就表示空闲的内存大小。heap size则表示最大可分配的内存大小,相当于heap alloc 和 heap free的和。

我们在看一下每个内存的分类情况:
Dalvik Heap:Dalvik虚拟机分配的内存。
Native Heap:本地代码申请的内存。
.so mmap 、.dex mmap … mmap 映射本地或虚拟机代码到使用的内存中。
Unknown 无法归类的其他项。主要包括大部分的本地分配。

App summary中内存,则统计的都是private的相关内存,其中包括了:
Java Heap java的堆内存
Native Heap 本地代码的内存
Code 代码申请的内存
Stack 栈内存
Graphics 物理内存
Private Other 其他内存
System 系统内存

Objects 就包含了android中所使用的对象了,ViewRootImpl用于分析window的数量。Activities则表示activity的数量Proxy Binders,则表示本地建立binder 的数量,WebViews则表示使用webview的数量,均是发生内存泄漏的高频区,利于分析。

SQL,则是数据库使用的内存情况。

你可能感兴趣的:(android)