Android系统的内存由几个不同的内存池中的几个不同的分配器管理。
目录:
- 系统内存
- 进程内存
2.1 procrank
2.2 smem tool - Dalvik Heap
- 调试Android应用内存占用情况
4.1 如何调试native进程内存分配情况
4.2 libc.debug.malloc
系统内存
通过查看 /proc/meminfo
,可以检查机器 上的内存视图。
如果使用DDMS,则可以查看机器,系统和不同执行进程使用的内存摘要。单击SysInfo选项卡,然后在窗格左上角的框中选择“Memory Usage”。
请注意,您可以通过将鼠标悬停在特定的饼图切片上来获取每个过程的数字。 数字以K和百分比显示。
进程内存
您可以通过检查/proc/<pid> / status
来查看单个进程的内存使用情况
有关内存使用的详细信息
- /proc/<pid>/statm
- /proc/<pid>/maps
- /proc/<pid>/smaps
'top'命令将显示VSS和RSS。另请参阅上面的ddms信息。
procrank
procrank将向您显示进程内存利用率的快速摘要。 默认情况下,它显示Vss,Rss,Pss和Uss,并按Vss排序。 但是,您可以控制排序顺序。
procrank源包含在system/extras/procrank
中,二进制文件位于android设备上的/system/ xbin中。
- Vss = virtual set size--虚拟集大小
- Rss = resident set size--常驻内存大小
- Pss = proportional set size--比例集大小
- Uss = unique set size--独占集大小
通常,您要观看的两个数字是Pss和Uss(Vss和Rss通常毫无价值,因为它们不能准确反映进程对与其他进程共享的页面的使用情况。)对整体内存负载的影响。 - Uss是进程独有的页面集。 这是当前终止应用程序时将释放的内存量。
- Pss是与其他进程共享的内存量,其计算方式是在共享它的进程之间平均分配额度。 这是在进程终止时不会释放的内存,但表示此进程“贡献”的数量
您还可以使用procrank查看每个进程的工作集大小,并重置工作集大小计数器。
这是procrank的用法:
# procrank -h Usage: procrank [ -W ] [ -v | -r | -p | -u | -h ] -v Sort by VSS. -r Sort by RSS. -p Sort by PSS. -u Sort by USS. (Default sort order is PSS.) -R Reverse sort order (default is descending). -w Display statistics for working set only. -W Reset working set of all processes. -h Display this help screen.
以下是一些示例输出:
# procrank PID Vss Rss Pss Uss cmdline 1217 36848K 35648K 17983K 13956K system_server 1276 32200K 32200K 14048K 10116K android.process.acore 1189 26920K 26920K 9293K 5500K zygote 1321 20328K 20328K 4743K 2344K android.process.media 1356 20360K 20360K 4621K 2148K com.android.email 1303 20184K 20184K 4381K 1724K com.android.settings 1271 19888K 19888K 4297K 1764K com.android.inputmethod.latin 1332 19560K 19560K 3993K 1620K com.android.alarmclock 1187 5068K 5068K 2119K 1476K /system/bin/mediaserver 1384 436K 436K 248K 236K procrank 1 212K 212K 200K 200K /init 753 572K 572K 171K 136K /system/bin/rild 748 340K 340K 163K 152K /system/bin/sh 751 388K 388K 156K 140K /system/bin/vold 1215 148K 148K 136K 136K /sbin/adbd 757 352K 352K 117K 92K /system/bin/dbus-daemon 760 404K 404K 104K 80K /system/bin/keystore 759 312K 312K 102K 88K /system/bin/installd 749 288K 288K 96K 84K /system/bin/servicemanager 752 244K 244K 71K 60K /system/bin/debuggerd
在此示例中,它显示本机守护程序和普通程序比基于Dalvik的服务和程序小一个数量级。 此外,即使是最小的Dalvik程序也需要大约1.5兆(Uss)才能运行。
smem tool
您可以通过smem查看非常详细的每个进程或系统范围的内存信息。安卓smem用法
Dalvik Heap
Dalvik堆由zygote预加载类和数据(从Android 2.2版开始加载超过1900个类)。当zygote分支启动Android应用程序时,新应用程序将获得此堆的写入时拷贝映射,这有助于减少内存和应用程序启动时间。
像许多其他语言的虚拟机一样,Dalvik在堆上进行垃圾收集。 每个VM进程中似乎都有一个单独的线程(称为HeapWorker),用于执行垃圾回收操作。
Dan Borstein谈到堆共享:
它在Android中用于分摊与所有活动VM进程中的公共库类相关联的大量有效只读数据(技术上可写但很少实际编写)的RAM占用空间。 系统在启动时预加载1000多个类,每个类至少消耗一小堆自身,包括经常指向其他对象的宿。 由预加载过程创建的堆与每个生成的VM进程共享写入时拷贝(但实际上并没有写得太多)。 这为每个进程节省了数百KB的"脏"的不可分页RAM,并且还有助于加速进程启动。
请参阅Dianne Hackborn的精彩文章调试Android应用程序内存使用情况
如何调试native进程内存分配情况
setprop dalvik.vm.checkjni true setprop libc.debug.malloc 10 setprop setprop dalvik.vm.jniopts forcecopy start stop
libc.debug.malloc
系统中的C库(仿生)支持在系统运行时使用malloc代码的不同调试版本的能力。
如果系统属性libc.debug.malloc的值不是0,那么在实例化进程时,C库将使用函数为该进程分配和释放内存。
(请注意,还有其他方法可以使用调试共享库malloc代码。也就是说,如果您在模拟器中运行,并且系统属性ro.kernel.memcheck的值不是'0', 然后你得到20的调试级别。注意,调试级别20只能在模拟器中使用。)
默认情况下,使用标准的malloc / free / calloc / realloc / memalign例程。 通过设置libc.debug.malloc,可以使用不同的例程来检查某些类型的内存错误(例如泄漏和溢出)。 这是通过使用这些不同的例程加载单独的共享库(.so)来完成的。
共享库的名称为:/system/lib/libc_malloc_debug_leak.so和/system/lib/libc_malloc_debug_qemu.so
(通过查看<android-source-root> /bionic/libc/bionic/malloc_debug_common.c获得信息)
libc.debug.malloc(调试级别值)支持的值为:
- 1 - 执行泄漏检测
- 5 - 填充分配的内存以检测溢出
- 10 - 填充内存并添加标记以检测溢出
- 20 - 为模拟器使用特殊的检测malloc / free例程
但我不确定这些共享库是否在生产设备中提供。