美文网首页
Android 内存之监控篇

Android 内存之监控篇

作者: PuHJ | 来源:发表于2019-10-08 17:12 被阅读0次

    一、前言

    内存问题主要会造成如下几个影响。第一、会发生OOM等异常,因为每个对象都会占用一定的内存,内存过多会影响对象的分配失败,严重者会导致设备重启。第二、内存过大,导致系统回收缓存内存,以及会加快GC频率,从而导致应用卡顿。

    内存的监控就尤为的重要。下面从几个方面来看Android对内存的监控,从而有助于观察内存变化。

    二、free

    free是轻量级的查看设备整体内存情况,具体例子如下:

    root@debian7:/proc/10# free
                 total       used       free     shared    buffers     cached
    Mem:       3044840     247692    2797148          0      19896     110084
    -/+ buffers/cache:     117712    2927128
    Swap:       901116          0     901116
    
    

    其中total = used + free,单位KB。
    对于-/+ buffers/cache行,是从有无缓冲来看。117712 = used - buffers - cached.
    2927128 = free + buffers + cached.

    三、/proc/meminfo文件

    /proc/meminfo是free的加强版,free中的数据也是从/proc/meminfo而来的。

    root@debian7:/proc/10# cat /proc/meminfo
    MemTotal:        3044840 kB  // RAM内存总大小
    MemFree:         2797520 kB  // RAM可用内存大小
    Buffers:           19912 kB  // Buffers缓存,文件缓存
    Cached:           110084 kB  // Cached缓存大小
    SwapCached:            0 kB
    Active:            97184 kB // 在活跃下的缓冲或高速缓冲存储器页面文件的大小
    Inactive:          94008 kB // 非活跃下的缓冲或高速缓冲存储器页面文件的大小
    Active(anon):      61312 kB // Active = Active(anon) + Active(file)
    Inactive(anon):     6008 kB
    Active(file):      35872 kB
    Inactive(file):    88000 kB
    Unevictable:           0 kB
    Mlocked:               0 kB
    SwapTotal:        901116 kB
    SwapFree:         901116 kB
    Dirty:                 0 kB // 等待被写回到磁盘的内存大小。
    Writeback:             0 kB // 正在被写回到磁盘的内存大小。
    AnonPages:         61188 kB
    Mapped:            24656 kB // 文件通过mmap分配的内存
    Shmem:              6132 kB
    Slab:              20412 kB //  内核数据结构缓存的大小。Linux中的Slab内存分配策略,相对于伙伴系统分配
    SReclaimable:       6288 kB
    SUnreclaim:        14124 kB
    KernelStack:        1000 kB
    PageTables:         4656 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:     2423536 kB
    Committed_AS:     535828 kB
    VmallocTotal:   34359738367 kB  // 总分配的虚拟地址空间
    VmallocUsed:      158760 kB  // 已分配的虚拟地址空间
    VmallocChunk:   34359576572 kB
    HardwareCorrupted:     0 kB
    AnonHugePages:         0 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB
    DirectMap4k:       45056 kB
    DirectMap2M:     2076672 kB
    DirectMap1G:     1048576 kB
    

    四、vmstat

    vmstat命令可以查看内存、IO和CPU等信息。

    语法命令:

    Usage: vmstat [ -n iterations ] [ -d delay ] [ -r header_repeat ]
        -n iterations     数据循环输出的次数
        -d delay          两次数据间的延迟时长(单位:S)
        -r header_repeat  循环多少次,再输出一次头信息行
    

    vmstat例子:

    root@debian7:/proc/10# vmstat
    procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
     0  0      0 2797396  19960 110084    0    0     1     0   13   25  0  0 100  0
    

    procs 程序

    • r : 运行的进程数量
    • b :等待IO阻塞的进程数量

    memory 内存

    • swpd : 虚拟内存(swap空间)已使用的大小
    • free :剩余的物理内存大小
    • buff : buff缓存大小
    • cache :文件等cache大小

    swap swap空间,内存够用时,si和so值都为0

    • si : swap空间写入内存的数据量;
    • so: 内存写入swap空间的数据量;

    IO

    • bi : 每秒从块设备读取块的数量
    • bo:每秒向块设备写入的块数量

    system

    • in : 每秒的中断次数
    • cs :等秒的上下文切换次数

    cpu

    • us : 用户态执行时间
    • sy : 内核态执行时间
    • id : 空闲时间(包括IO等待时间)
    • wa : 等待IO时间

    五、/proc/[PID]/status

    root@p212:/data/dropbear # cat /proc/4943/status
    Name:   XXXXX
    State:  S (sleeping) : 状态
    Tgid:   4943 :线程组ID
    Pid:    4943 :进程ID,同TGID,说明是主线程
    PPid:   3769 :父进程ID
    TracerPid:      0
    Uid:    10039   10039   10039   10039
    Gid:    10039   10039   10039   10039
    Ngid:   0
    FDSize: 64 :FDSize是当前分配过的文件描述符数量
    Groups: 3003 9997 50039 : groups表示启动这个进程的用户所在的组.
    VmPeak:  1503968 kB :当前进程运行过程中占用内存的峰值
    VmSize:   878224 kB  :虚拟内存大小
    VmLck:         0 kB
    VmPin:         0 kB
    VmHWM:     40040 kB :分配到物理内存的峰值
    VmRSS:     38120 kB : 虚拟内存驻留集合大小
    VmData:   134084 kB :进程数据段的大小
    VmStk:      8196 kB : 进程堆栈段的大小
    VmExe:        20 kB
    VmLib:     69224 kB
    VmPTE:       440 kB
    VmSwap:        0 kB : 进程占用Swap的大小.
    Threads:        22 :线程数量
    SigQ:   0/2462
    SigPnd: 0000000000000000 : 存储了该线程的待处理信号
    ShdPnd: 0000000000000000 : 存储了该线程组的待处理信号
    SigBlk: 0000000000001204 : 存放被阻塞的信号
    SigIgn: 0000000000000000 : 存放可被忽略的信号
    SigCgt: 00000002000094f8
    CapInh: 0000000000000000
    CapPrm: 0000000000000000
    CapEff: 0000000000000000
    CapBnd: 0000000000000000
    Seccomp:        0
    Cpus_allowed:   f
    Cpus_allowed_list:      0-3
    voluntary_ctxt_switches:        358 : 进程主动切换上下文的次数(资源得不到等)
    nonvoluntary_ctxt_switches:     400 : 进程被动切换上下文的次数.
    
    

    六、Android#Runtime

    Android中提供了一些接口,供使用者调用,可定时的采集以下几种内存情况,从而判断当前进程内存情况。

            Runtime runtime = Runtime.getRuntime();
            long javaMax = runtime.maxMemory();  //  JVM可分配的最大内存
            long javaTotal = runtime.totalMemory();  //  当前分配的内存
            long javaUsed = javaTotal - runtime.freeMemory();  //  当前使用的内存
            
            float proportion = (float) javaUsed / javaMax;
            Log.e("TAG", "onResume: javaMax="+javaMax+";javaTotal="+javaTotal+";javaUsed="+javaUsed+";proportion="+proportion);
    
    

    七、Android#onLowMemory

    在Android4.0中提供了一些监听内存的接口OnLowMemory和onTrimMemory

    【一】、OnLowMemory

    OnLowMemory是ComponentCallbacks接口中的方法,当系统内存不足,要被杀死后台程序时,会调用该方法。

    可用在Application、Activity、Fragement、Service和ContentProvider中

    【二】、onTrimMemory

    因为OnLowMemory的接口太简单了,并没有提供内存的状态,在ComponentCallbacks2中丰富了回调了接口。

    public interface ComponentCallbacks2 extends ComponentCallbacks {
    
        /** @hide */
        @IntDef(prefix = { "TRIM_MEMORY_" }, value = {
                TRIM_MEMORY_COMPLETE,
                TRIM_MEMORY_MODERATE,
                TRIM_MEMORY_BACKGROUND,
                TRIM_MEMORY_UI_HIDDEN,
                TRIM_MEMORY_RUNNING_CRITICAL,
                TRIM_MEMORY_RUNNING_LOW,
                TRIM_MEMORY_RUNNING_MODERATE,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface TrimMemoryLevel {}
    
        static final int TRIM_MEMORY_COMPLETE = 80;
        
        static final int TRIM_MEMORY_MODERATE = 60;
       
        static final int TRIM_MEMORY_BACKGROUND = 40;
        
        static final int TRIM_MEMORY_UI_HIDDEN = 20;
    
        static final int TRIM_MEMORY_RUNNING_CRITICAL = 15;
    
        static final int TRIM_MEMORY_RUNNING_LOW = 10;
    
        static final int TRIM_MEMORY_RUNNING_MODERATE = 5;
    
        void onTrimMemory(@TrimMemoryLevel int level);
    }
    

    同onLowMemory一致,也可用在Application、Activity、Fragement、Service和ContentProvider中。

    • TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理
    • TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。
    • TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。
    • TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。
    • TRIM_MEMORY_RUNNING_CRITICAL:内存不足,并且该进程不是消耗性的后台进程,需要清理内存
    • TRIM_MEMORY_RUNNING_LOW:内存不足,并且该进程不是消耗性的后台进程,需要清理内存
    • TRIM_MEMORY_RUNNING_MODERATE:内存不足,并且该进程不是消耗性的后台进程,需要清理内存

    八、dumpsys

    通过adb shell dumpsys meminfo [pid | 包名] 可以查看单个APP内存情况

    如下:

    Applications Memory Usage (kB):
    Uptime: 31564143 Realtime: 31564143
    
    ** MEMINFO in pid 30712 [XXX] **
                       Pss  Private  Private  Swapped     Heap     Heap     Heap
                     Total    Dirty    Clean    Dirty     Size    Alloc     Free
                    ------   ------   ------   ------   ------   ------   ------
      Native Heap     2196     2092        0        0     6144     4855     1288
      Dalvik Heap     1517     1396        0        0     3873     2449     1424
     Dalvik Other      373      372        0        0
            Stack      132      132        0        0
           Ashmem        2        0        0        0
        Other dev        5        0        4        0
         .so mmap     1148       96      156        0
        .apk mmap      326        0       28        0
        .ttf mmap       88        0       76        0
        .dex mmap     2844        4     2840        0
        .oat mmap     1204        0      164        0
        .art mmap     1321      476      368        0
       Other mmap       11        8        0        0
        GL mtrack     2960     2960        0        0
          Unknown      121      120        0        0
            TOTAL    14248     7656     3636        0    10017     7304     2712
    
     App Summary
                           Pss(KB)
                            ------
               Java Heap:     2240
             Native Heap:     2092
                    Code:     3364
                   Stack:      132
                Graphics:     2960
           Private Other:      504
                  System:     2956
    
                   TOTAL:    14248      TOTAL SWAP (KB):        0
    
     Objects
                   Views:       15         ViewRootImpl:        1
             AppContexts:        2           Activities:        1
                  Assets:        2        AssetManagers:        2
           Local Binders:        9        Proxy Binders:       12
           Parcel memory:        3         Parcel count:       14
        Death Recipients:        0      OpenSSL Sockets:        0
    
     SQL
             MEMORY_USED:        0
      PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0
    
    
    第一部分主要字段解析:
    • Native Heap : Native堆大小
    • Dalvik Heap : java堆大小
    • Stack :栈大小
    • Ashmem : 匿名共享内存大小
    • .so mmap : 映射的so库大小
    • .apk mmap:apk占用内存大小
    • .dex mmap : dex占用内存大小
    • Pss Total :物理内存总大小
    • Private Dirty : 进程私有的内存,相对磁盘数据有改动的内存
    • Private Clean : 进程私有的内存,相对磁盘数据没有修改的内存
    • Heap Size : Dalvik中,同runtime.totalMemory()
    • Heap Alloc : Dalvik中,同runtime.totalMemory()-runtime.freeMemory()
    • Heap Free : Dalvik中,同runtime.freeMemory()
    App Summary主要字段解析:
    • Java Heap : Dalvik Heap 中的 Private Dirty + .art mmap 的 Private Dirty + Private Clean
    • Native Heap :Native Heap
    • Code : .so mmap+ .jar mmap + .apk mmap + .ttf mmap + .dex mmap + .oat mmap的 Private Dirty + Private Clean
    • Stack :Stack
    Objects主要字段解析:
    • Views :存活的view的个数
    • ViewRootImpl : 存活的ViewRootImpl数量
    • AppContexts :APP整个上下文数量
    • Activities : 存活的Activity数量

    相关文章

      网友评论

          本文标题:Android 内存之监控篇

          本文链接:https://www.haomeiwen.com/subject/dfkbpctx.html