整理下Android内存优化常用的几种工具,top命令、adb shell dumpsys meminfo、Memory Profiler、LeakCanary、MAT


(资料图片)

1. top

top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况。

查看top命令的用法

$ adb shell top --helpusage: top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-m LINES] [-d SECONDS] [-p PID,] [-u USER,]Show process activity in real time.-H  Show threads-k  Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID)-o  Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)-O  Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)-s  Sort by field number (1-X, default 9)-b  Batch mode (no tty)-d  Delay SECONDS between each cycle (default 3)-m  Maximum number of tasks to show-n  Exit after NUMBER iterations-p  Show these PIDs-u  Show these USERs-q  Quiet (no header lines)Cursor LEFT/RIGHT to change sort, UP/DOWN move list, space to forceupdate, R to reverse sort, Q to exit.复制代码

使用top命令显示一次进程信息,以便讲解进程信息中各字段的含义

^[[41;173RTasks: 754 total,   1 running, 753 sleeping,   0 stopped,   0 zombie  Mem:      5.5G total,      5.4G used,      165M free,       76M buffers Swap:      2.5G total,      789M used,      1.7G free,      2.4G cached800%cpu 100%user   3%nice  54%sys 641%idle   0%iow   3%irq   0%sirq   0%host  PID USER         PR  NI VIRT  RES  SHR S[%CPU] %MEM     TIME+ ARGS15962 u0_a894      10 -10 6.6G 187M  76M S 75.6   3.2   8:16.55 asia.bluepay.cl+  785 system       -2  -8 325M  13M 7.6M S 29.7   0.2  84:03.91 surfaceflinger25255 shell        20   0  35M 2.7M 1.6M R 21.6   0.0   0:00.16 top -n 1  739 system       -3  -8 177M 3.6M 2.2M S 10.8   0.0  16:00.36 android.hardwar+16154 u0_i9086     10 -10 1.3G  40M  19M S  5.4   0.6   0:46.18 com.google.andr+13912 u0_a87       20   0  17G 197M  86M S  5.4   3.4  23:56.88 com.tencent.mm24789 root         RT  -2    0    0    0 D  2.7   0.0   0:01.36 [mdss_fb0]24704 root         20   0    0    0    0 S  2.7   0.0   0:01.20 [kworker/u16:12]20096 u0_a94       30  10 6.1G 137M  53M S  2.7   2.3   0:31.45 com.xiaomi.mark+ 2272 system       18  -2 8.7G 407M 267M S  2.7   7.1 191:11.32 system_server  744 system       RT   0 1.3G 1.6M 1.4M S  2.7   0.0  72:22.41 android.hardwar+  442 root         RT   0    0    0    0 S  2.7   0.0   5:59.68 [cfinteractive]  291 root         -3   0    0    0    0 S  2.7   0.0   5:00.17 [kgsl_worker_th+   10 root         20   0    0    0    0 S  2.7   0.0   1:55.84 [rcuop/0]    7 root         20   0    0    0    0 S  2.7   0.0   2:46.82 [rcu_preempt]25186 shell        20   0  34M 1.9M 1.4M S  0.0   0.0   0:00.71 logcat -v long +25181 root         20   0    0    0    0 S  0.0   0.0   0:00.00 [kworker/2:3]25137 root         20   0    0    0    0 S  0.0   0.0   0:00.00 [kworker/1:3]25118 system       20   0 5.2G  83M  54M S  0.0   1.4   0:01.05 com.android.set+24946 u0_a57       20   0 5.1G  60M  37M S  0.0   1.0   0:00.82 com.xiaomi.acco+复制代码

第 1 行:进程信息

总共(total):754个运行中(running)状态:1个休眠(sleeping)状态:753个停止(stopped)状态:0个僵尸(zombie)状态:0个

第 2 行:内存信息

5.5G total:物理内存总量5.4G used:使用中的内存量165M free:空闲内存量76M buffers: 缓存的内存量

第 3 行:Swap分区信息

2.5G total:交换区总量789M used:使用的交换区大小1.7G free:空闲交换区大小2.4G cached:缓冲的交换区大小

内存监控时,可以监控swap交换分区的used,如果这个数值在不断的变化,说明内核在不断进行内存和swap的数据交换,这是内存不够用了。

第 4 行:CPU信息

800%cpu:8核cpu100%user:用户进程使用CPU占比3%nice:优先值为负的进程占比54%sys:内核进程使用CPU占比641%idle:除IO等待时间以外的其它等待时间占比0%iow:IO等待时间占比3%irq:硬中断时间占比0%sirq:软中断时间占比

第 5 行及以下:各进程的状态监控

PID:进程idUSER:进程所属用户PR:进程优先级NI:nice值,负值表示高优先级,正值表示低优先级VIRT:进程使用的虚拟内存总量,VIRT=SWAP+RESRES:进程使用的、未被换出的物理内存大小,RES=CODE+DATASHR:共享内存大小S:进程状态%CPU:上次更新到现在的CPU占用时间比%MEM:使用物理内存占比TIME+:进程时间的CPU时间总计,单位1/100秒ARGS:进程名

2. dumpsys meminfo

首先了解下Android中最重要的四大内存指标的概念

我们主要使用USS和PSS来衡量进程的内存使用情况

dumpsys meminfo命令展示的是系统整体内存情况,内存项按进程进行分类

$ adb shell dumpsys meminfoApplications Memory Usage (in Kilobytes):Uptime: 168829244 Realtime: 1465769995// 根据进程PSS占用值从大到小排序Total PSS by process:    272,029K: system (pid 2272)    234,043K: com.tencent.mm (pid 13912 / activities)    185,914K: com.android.systemui (pid 13606)    107,294K: com.tencent.mm:appbrand0 (pid 5563)    101,526K: com.tencent.mm:toolsmp (pid 9287)     96,645K: com.miui.home (pid 15116 / activities)    ...// 以oom来划分,会详细列举所有的类别的进程Total PSS by OOM adjustment:    411,619K: Native         62,553K: android.hardware.camera.provider@2.4-service (pid 730)         21,630K: logd (pid 579)         16,179K: surfaceflinger (pid 785)         ...    272,029K: System        272,029K: system (pid 2272)    361,942K: Persistent        185,914K: com.android.systemui (pid 13606)         37,917K: com.android.phone (pid 2836)         23,510K: com.miui.contentcatcher (pid 3717)         ...     36,142K: Persistent Service         36,142K: com.android.bluetooth (pid 26472)    101,198K: Foreground         72,743K: com.miui.securitycenter.remote (pid 4125)         28,455K: com.android.settings (pid 30919 / activities)    338,088K: Visible         96,645K: com.miui.home (pid 15116 / activities)         46,939K: com.miui.personalassistant (pid 31043)         36,491K: com.xiaomi.xmsf (pid 4197)         ...     47,703K: Perceptible         17,826K: com.xiaomi.metoknlp (pid 4477)         10,748K: com.lbe.security.miui (pid 5097)         10,528K: com.xiaomi.location.fused (pid 4563)          8,601K: com.miui.mishare.connectivity (pid 4227)     13,088K: Perceptible Low         13,088K: com.miui.analytics (pid 19306)    234,043K: Backup        234,043K: com.tencent.mm (pid 13912 / activities)     22,028K: A Services         22,028K: com.miui.powerkeeper (pid 29762)    198,787K: Previous         33,375K: com.android.quicksearchbox (pid 31023)         23,278K: com.google.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0 (pid 16154)    171,434K: B Services         45,962K: com.tencent.mm:push (pid 14095)         31,514K: com.tencent.mobileqq:MSF (pid 12051)         22,691K: com.xiaomi.mi_connect_service (pid 22821)         ...    538,062K: Cached        107,294K: com.tencent.mm:appbrand0 (pid 5563)        101,526K: com.tencent.mm:toolsmp (pid 9287)         72,112K: com.tencent.mm:tools (pid 9187)        ...// 按内存的类别来进行划分Total PSS by category:    692,040K: Native    328,722K: Dalvik    199,826K: .art mmap    129,981K: .oat mmap    126,624K: .dex mmap    124,509K: Unknown     92,666K: .so mmap     68,189K: Dalvik Other     53,491K: .apk mmap     44,104K: Gfx dev     28,099K: Other mmap     24,960K: .jar mmap      7,956K: Ashmem      3,700K: Stack      3,368K: Other dev        450K: .ttf mmap          4K: Cursor          0K: EGL mtrack          0K: GL mtrack          0K: Other mtrack// 手机整体内存使用情况Total RAM: 5,862,068K (status normal) Free RAM: 3,794,646K (  538,062K cached pss + 3,189,244K cached kernel +         0K cached ion +    67,340K free) Used RAM: 2,657,473K (2,208,101K used pss +   449,372K kernel) Lost RAM:   487,987K     ZRAM:   219,996K physical used for   826,852K in swap (2,621,436K total swap)   Tuning: 256 (large 512), oom   322,560K, restore limit   107,520K (high-end-gfx)复制代码

查看单个进程的内存信息,命令如下

adb shell dumpsys meminfo [pid | packageName]复制代码

我们查看下微信的内存信息

$ adb shell dumpsys meminfo com.tencent.mmApplications Memory Usage (in Kilobytes):Uptime: 169473031 Realtime: 1466413783** MEMINFO in pid 13912 [com.tencent.mm] **                   Pss  Private  Private  SwapPss     Heap     Heap     Heap                 Total    Dirty    Clean    Dirty     Size    Alloc     Free                ------   ------   ------   ------   ------   ------   ------  Native Heap    51987    51924        0    61931   159044   139335    19708  Dalvik Heap    74302    74272        8     2633   209170   184594    24576 Dalvik Other    10136    10136        0      290        Stack       84       84        0        8       Ashmem        2        0        0        0      Gfx dev     8808     8808        0        0    Other dev      156        0      156        0     .so mmap     9984      984     7436     8493    .jar mmap     1428        0      560        0    .apk mmap     2942        0     1008        0    .ttf mmap     1221        0     1064        0    .dex mmap    31302       44    30004      528    .oat mmap     2688        0      232        0    .art mmap     2792     2352       40     3334   Other mmap     6932     2752      632        0      Unknown     4247     4232        4     7493        TOTAL   293721   155588    41144    84710   368214   323929    44284 App Summary                       Pss(KB)                        ------           Java Heap:    76664         Native Heap:    51924                Code:    41332               Stack:       84            Graphics:     8808       Private Other:    17920              System:    96989               TOTAL:   293721       TOTAL SWAP PSS:    84710 Objects               Views:      623         ViewRootImpl:        1         AppContexts:        9           Activities:        1              Assets:       12        AssetManagers:        0       Local Binders:      198        Proxy Binders:      183       Parcel memory:       46         Parcel count:      185    Death Recipients:      125      OpenSSL Sockets:        1            WebViews:        0 SQL         MEMORY_USED:      156  PAGECACHE_OVERFLOW:       13          MALLOC_SIZE:      117 DATABASES      pgsz     dbsz   Lookaside(b)          cache  Dbname         4       28             46       721/26/4  /data/user/0/com.tencent.mm/databases/Scheduler.db Asset Allocations    : 409K    : 12K    : 1031K复制代码
App Summary各项指标解读如下,通常我们需要重点关注Java Heap和Native Heap的大小,如果持续上升,有可能存在内存泄露。Objects中Views、Activities、AppContexts的异常可以判断有内存泄露,比如刚退出应用,查看Activites是否为0,如果不为0,则有Activity没有销毁。

3. Memory Profiler

Memory Profiler是 Android Profiler 中的一个组件,实时图表展示应用内存使用量,识别内存泄露和抖动,提供捕获堆转储,强制GC以及跟踪内存分配的能力。

Android Profiler官方文档

4. Leak Canary

非常好用的内存泄露检测工具,对于Activity/Fragment的内存泄露检测非常方便。

Square公司开源 官网地址,原理后面单独分析。

5. MAT

MAT是Memory Analyzer tool的缩写,是一个非常全面的分析工具,使用相对复杂点。 关于安装和配置有很多很好的文章结束,这里就不单独讲了,后面分析具体案例。

Android 内存优化篇 – 使用profile 和 MAT 工具进行内存泄漏检测

使用Android Studio和MAT进行内存泄漏分析

内存问题高效分析方法

接入LeakCanary,监控所有Activity和Fragment的释放,App所有功能跑一遍,观察是否有抓到内存泄露的地方,分析引用链找到并解决问题,如此反复,直到LeakCanary检查不到内存泄露。adb shell dumpsys meminfo命令查看退出界面后Objects的Views和Activities数目,特别是退出App后数目为否为0。打开Android Studio Memory Profiler,反复打开关闭页面多次,点击GC,如果内存没有恢复到之前的数值,则可能发生了内存泄露。再点击Profiler的垃圾桶图标旁的heap dump按钮查看当面内存堆栈情况,按包名找到当前测试的Activity,如果存在多份实例,则很可能发生了内存泄露。对于可疑的页面dump出内存快照文件,转换后用MAT打开,针对性的分析。观察Memory Profiler每个页面打开时的内存波峰和抖动情况,针对性分析。开发者选项中打开“不保留后台活动”,App运行一段时间后退到后台,触发GC,dump内存快照。MAT分析静态内容是否有可以优化的地方,比如图片缓存、单例、内存缓存等。

关键词: