整理下Android内存优化常用的几种工具,top命令、adb shell dumpsys meminfo、Memory Profiler、LeakCanary、MAT
1. toptop命令是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核cpu 100%user:用户进程使用CPU占比 3%nice:优先值为负的进程占比 54%sys:内核进程使用CPU占比 641%idle:除IO等待时间以外的其它等待时间占比 0%iow:IO等待时间占比 3%irq:硬中断时间占比 0%sirq:软中断时间占比 第 5 行及以下:各进程的状态监控 PID:进程id USER:进程所属用户 PR:进程优先级 NI:nice值,负值表示高优先级,正值表示低优先级 VIRT:进程使用的虚拟内存总量,VIRT=SWAP+RES RES:进程使用的、未被换出的物理内存大小,RES=CODE+DATA SHR:共享内存大小 S:进程状态 %CPU:上次更新到现在的CPU占用时间比 %MEM:使用物理内存占比 TIME+:进程时间的CPU时间总计,单位1/100秒 ARGS:进程名 2. dumpsys meminfo首先了解下Android中最重要的四大内存指标的概念
指标 全称 含义 等价 USS Unique Set Size 独占物理内存 进程独占的内存 PSS Proportional Set Size 实际使用物理内存 PSS = USS + 按比例包含共享库内存 RSS Resident Set Size 实际使用物理内存 RSS = USS + 包含共享库内存 VSS Virtual Set Size 虚拟耗用内存 VSS = 进程占用内存(包括虚拟耗用) + 共享库(包括比例分配部分)我们主要使用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没有销毁。
Memory Profiler是 Android Profiler 中的一个组件,实时图表展示应用内存使用量,识别内存泄露和抖动,提供捕获堆转储,强制GC以及跟踪内存分配的能力。
Android Profiler文档
4. Leak Canary非常好用的内存泄露检测工具,对于Activity/Fragment的内存泄露检测非常方便。
Square公司开源 官网地址,原理后面单独分析。
5. MATMAT是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分析静态内容是否有可以优化的地方,比如图片缓存、单例、内存缓存等。