Android(安卓)内存查看常用命令
事情的终局强如事情的起头;存心忍耐的,胜过居心骄傲的。—传道书7:8
RAM(random-access memory)即内存的使用情况对系统的性能影响很大,OOM问题、内存泄露、程序卡顿等诸多问题,都跟不合理的内存使用相关,并且这类问题一般都比较隐晦,要解决该类问题,熟悉内存查看的方法很有必要。
本篇博文介绍Android平台上常用的内存观测方法。
procrank与procmem
这两个命令均需要root权限才能运行。
procrank
procrank可以快速的总览当前系统各个进程的内存使用情况,其主要展示了4个指标:
- Vss(virtual set size): 进程可访问的内存大小,包含了共享内存。Android系统中大量的内存空间会被多个进程共享,比如一个进程在运行期间会调用到其他进程,那么Vss也就将调用到的其它进程的内存统计进来了。
- Rss(resident set size): 进程实际使用的内存大小,同样也包含了共享内存,但它只将实际用到的共享内存统计入内。
- Pss(proportional set size): 进程自身内存大小+按比例分配的共享内存大小。
- Uss(unique set size): 进程自身的内存大小,不包括使用到的其他共享内存。程序退出后,系统就会多出Uss大小的内存出来。
举个例子说明下:假如有进程A,其自身运行期间的私有内存大小为a,进程B运行期间占据了b大小的内存。
A运行期间需要依赖B,则Vss=a+b。
A依赖B,但只是用到了B进程下的部分内存区域,大小为b1。则Rss=a+b1(b1<=b)
除了A以外,还有3个进程也同样在使用B,则Pss=a+b/(1+3)
只统计A进程自身占用的内存,则Uss=a
procrank的使用说明
# procrank -hUsage: procrank [ -W ] [ -v | -r | -p | -u | -s | -h ] -v Sort by VSS. -r Sort by RSS. -p Sort by PSS. -u Sort by USS. -s Sort by swap. (Default sort order is PSS.) -R Reverse sort order (default is descending). -c Only show cached (storage backed) pages -C Only show non-cached (ram/swap backed) pages -k Only show pages collapsed by KSM -w Display statistics for working set only. -W Reset working set of all processes. -h Display this help screen.
其运行结果如下:
PID Vss Rss Pss Uss cmdline 3062 1735540K 131548K 85448K 78648K system_server 3428 1028392K 115896K 74462K 68900K com.android.systemui26426 1012992K 83272K 42890K 39664K com.android.settings 3806 1001248K 81064K 41639K 38840K com.android.phone 353 152208K 40524K 28086K 26516K /system/bin/cameraserver 3414 978800K 64344K 27342K 25120K com.google.android.inputmethod.pinyin 9885 1643528K 64880K 24821K 22012K com.android.mms
分析内存问题主要关注的是Uss跟Pss,尤其是Uss.因为Vss和Rss包含了共享内存,单个进程分析内存大小时,会有干扰。
由于procrank会列出整个系统进程的内存信息,而更多时候我们往往只关心特定进程的内存信息。可以用下面的shell语句过滤出我们关心的内容。
while true;do adb shell procrank|grep ; sleep 6;done
上述命令会每隔6s打印出关心的进程内存信息。
procmem
procrank命令从宏观上给出了进程的内存总体情况,但如果需要详细分析某个进程的内存分配细节,这个时候就需要procmem出场了。
procmem使用说明:
# procmemUsage: procmem [ -w | -W ] [ -p | -m ] [ -h ] pid -w Displays statistics for the working set only. -W Resets the working set of the process. -p Sort by PSS. -m Sort by mapping order (as read from /proc). -h Hide maps with no RSS.
比如我们查看settings应用的内存分布:
# procmem -m 26426 (26426为settings的pid) Vss Rss Pss Uss ShCl ShDi PrCl PrDi Name------- ------- ------- ------- ------- ------- ------- ------- 2084K 0K 0K 0K 0K 0K 0K 0K /dev/ashmem/dalvik-main space (deleted)194524K 0K 0K 0K 0K 0K 0K 0K /dev/ashmem/dalvik-main space (deleted) 12560K 10492K 10492K 10492K 0K 0K 10488K 4K /dev/ashmem/dalvik-main space 1 (deleted) 1780K 0K 0K 0K 0K 0K 0K 0K /dev/ashmem/dalvik-main space 1 (deleted)182268K 0K 0K 0K 0K 0K 0K 0K /dev/ashmem/dalvik-main space 1 (deleted) 7436K 7436K 4277K 4172K 3264K 0K 4172K 0K /data/dalvik-cache/arm/[email protected]@boot.art 31116K 15260K 1696K 124K 15136K 0K 124K 0K /data/dalvik-cache/arm/[email protected]@boot.oat 4K 4K 0K 0K 4K 0K 0K 0K /data/dalvik-cache/arm/[email protected]@boot.oat 0K 0K 0K 0K 0K 0K 0K 0K [vectors]------- ------- ------- ------- ------- ------- ------- ------- 1130688K 148940K 108346K 104332K 44512K 96K 62100K 42452K TOTAL
中间大量的输出结果省略。
从procmem输出的结果可以看到它给出了内存是如何分配的细节,但面对这茫茫多的输出数据,我们该如何从中寻找问题点呢?
内存异常问题往往伴随着内存泄露,而内存泄露的本质就是申请的内存区域得不到正常释放,表现在procmem的输出结果就是多条同名的记录出现。因此如果发现procmem输出的结果里某条记录出现次数过多,比如五六百次,那么我们应当小心对待了。
dumpsys meminfo
dumpsys meminfo
也是分析内存的一把利器,如果不跟进程名或者进程号,则输出系统整体的内存情况,跟进程名则输出该进程的内存分配情况。
# adb shell dumpsys meminfo 26426Applications Memory Usage (in Kilobytes):Uptime: 206814437 Realtime: 374715375** MEMINFO in pid 26426 [com.android.settings] ** Pss Private Private Swap Heap Heap Heap Total Dirty Clean Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ ------ Native Heap 32062 32016 0 0 67584 27961 39622 Dalvik Heap 9623 9504 0 0 21384 9096 12288 Dalvik Other 4857 4824 0 0 Stack 404 404 0 0 Ashmem 2 0 0 0 Gfx dev 40220 40220 0 0 Other dev 6 0 4 0 .so mmap 1258 184 16 0 .jar mmap 8 8 0 0 .apk mmap 865 0 392 0 .ttf mmap 63 0 8 0 .dex mmap 6464 8 6456 0 .oat mmap 1694 0 124 0 .art mmap 4280 4172 0 0 Other mmap 563 4 156 0 EGL mtrack 13056 13056 0 0 Unknown 601 600 0 0 TOTAL 116026 105000 7156 0 88968 37057 51910 App Summary Pss(KB) ------ Java Heap: 13676 Native Heap: 32016 Code: 7196 Stack: 404 Graphics: 53276 Private Other: 5588 System: 3870 TOTAL: 116026 TOTAL SWAP (KB): 0 Objects Views: 985 ViewRootImpl: 3 AppContexts: 11 Activities: 7 Assets: 5 AssetManagers: 4 Local Binders: 83 Proxy Binders: 40 Parcel memory: 389 Parcel count: 26 Death Recipients: 0 OpenSSL Sockets: 0 WebViews: 0 SQL MEMORY_USED: 339 PAGECACHE_OVERFLOW: 178 MALLOC_SIZE: 117 DATABASES pgsz dbsz Lookaside(b) cache Dbname 4 228 95 469/191/4 /data/user_de/0/com.android.settings/databases/search_index.db
横轴的几个重要参数:
- Pss Total:按比例分配占用内存 (PSS) 总量,与procrank里的Pss含义一样。
- Private Dirty: 进程私有的内存分配量,当进程退出,将有 Private Dirty大小的内存被系统回收。Private Dirty是已被修改而必须保持在 RAM 中的 RAM 页,相对应的Private Clean指RAM已从某个持久性文件(例如正在执行的代码)映射的 RAM 页,如果一段时间不用,可以移出分页。
- Heap Size:进程当前可访问到的堆内存大小,包含了共享的其他进程内存。
- Heap Alloc:进程当前已经占有的堆内存大小。
纵轴的几个重要参数:
- Unknown:系统无法将其分类到其他更具体的一个项中的内存,当Unknown指持续增大,且不会明显回落,很可能是native的内存泄漏了。
- AppContexts & Activities:进程中当前活动的应用 Context 和 Activity 对象数量,它们不断增长则表示有内存泄漏。
proc节点下隐藏的内存信息
/proc/[pid]节点下的内容包含了该进程更为详细的信息。不过查看它需要root权限。事实上不光内存信息,有关该进程的各种信息基本都能在该节点下找到。
# cd /proc/26426# lsattr clear_refs coredump_filter exe limits maps mounts ns oom_score_adj reclaim sessionid stat syscall auxv cmdline cwd fd loginuid mem mountstats oom_adj pagemap root smaps statm task cgroup comm environ fdinfo make-it-fail mountinfo net oom_score personality schedstat stack status wchan
以上展现了进程26426的相关信息,它们都被记录在对应的文件节点上。分析内存问题主要看maps节点,它会记录26426进程的详细内存映射关系
# cat maps |head 12c00000-12e09000 ---p 00000000 00:04 12528 /dev/ashmem/dalvik-main space (deleted)12e09000-1ec00000 ---p 00209000 00:04 12528 /dev/ashmem/dalvik-main space (deleted)32c00000-33844000 rw-p 00000000 00:04 12529 /dev/ashmem/dalvik-main space 1 (deleted)33844000-33a01000 ---p 00c44000 00:04 12529 /dev/ashmem/dalvik-main space 1 (deleted)33a01000-3ec00000 rw-p 00e01000 00:04 12529 /dev/ashmem/dalvik-main space 1 (deleted)70e4b000-7158e000 rw-p 00000000 103:0c 497764 /data/dalvik-cache/arm/system@framework@boot.art7158e000-733f1000 r--p 00000000 103:0c 497763 /data/dalvik-cache/arm/system@framework@boot.oat733f1000-733f2000 r-xp 01e63000 103:0c 497763 /data/dalvik-cache/arm/system@framework@boot.oat733f2000-733f3000 r--p 01e64000 103:0c 497763 /data/dalvik-cache/arm/system@framework@boot.oat733f3000-733f4000 rw-p 01e65000 103:0c 497763 /data/dalvik-cache/arm/system@framework@boot.oat
procmem获取到的信息就跟maps节点记录的一样,maps更加详细的标示出了内存分配的起至位置。
参考链接
http://stevevallay.github.io/blog/2014/11/17/memory-leak/
https://androidzhibinw.github.io/android/app/startup/activity/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/%E5%90%AF%E5%8A%A8/%E5%88%86%E6%9E%90/2015/09/21/android-app-startup-process/
http://shooting.logdown.com/posts/318965-android-memory-allocation
https://developer.android.com/studio/profile/investigate-ram.html?hl=zh-cn
更多相关文章
- 手把手带你搭建 Elasticsearch 集群
- 一款霸榜 GitHub 的开源 Linux 资源监视器!
- Android常见40道原理性面试,去面试之前必须要了解的知识点
- android使用logwrapper进行log重定向
- Android(安卓)系统启动流程解析-从开机到Dalvik VM
- 抖音BoostMultiDex优化实践:Android低版本上APP首次启动时间减少8
- .如何避免Android内存泄漏
- Android(安卓)IPC 进程间通信实现理解
- Framework笔记 | Android(安卓)Framework用到了哪些IPC方式,分别