目录
进程的内存信息概述
关键的术语
测试步骤
测试步骤
数据处理
数据分析:
进程内存信息
Dumpsys meminfo -a PID
Procrank
Procmem PID
特殊内存信息
Mali
ION(multi-media,gralloc)
进程地址空间信息
/proc/pid/smaps
Showmap PID
进程的内存使用优化
进程的内存信息概述
进程使用内存,分为两大类:(这两大类都会在进程地址空间中得到体现)
- 常规内存:
- 普通malloc,free的heap; 进程的stack; 以及java层的dalvik-alloc space等等。基本上都是Anonymous匿名页
- 文件映射;包括映射.so的代码段,XP代码段,RO数据段,RW数据段,BSS数据段;以及apk, 以及art等等。其中有部分是文件缓存(比如XP代码段),有部分是Anonymous匿名页(比如RW数据段)。
- 特殊内存:一些特殊的,使用物理内存直接mmap到用户空间的内存;或者由内核模块配合分配,然后mmap到用户空间的内存。
- 使用的mali分配的内存,
- 多媒体内存管理ION分配的内存,
- 或者是framebuffer的内存,等等。
而常规内存分为两类:
- 匿名页:Anonymous。它可以被交换到swap分区;因此一个进程占用的匿名页的总数(堆,栈) = 没有被交换出去的 + 被交换出去的部分;是可以准确量化的。因此测试目前重点关注此项。
- 文件缓存:Filecache。这部分大小会根据内存大小,回收策略等等变化会很大,难以统计出某个APP的filecache到底有多大:
- 内存不紧张时,文件缓存尽可能的多(高效); 这样APP的文件缓存就大;
- 内存紧张时,文件缓存就会被回收,此时APP的文件缓存就小。
- 而且没有任何记录项用来记录一个进程的某段文件映射被drop了多少文件缓存。
- 当filecache小到一定程度后,APP的运行将极端的不顺畅;但无法量化。
- 只能假设内存相当充足时,这部分Filecache会尽可能的大,才能接近峰值。
关键的术语
下属内存统计中VSS,PSS,USS均包含了Anonymous + Filecache。而Swap,Pswap,Uswap均只包含被交换出去的Anonymous。
- VSS:
VSS ( 等同于 ps 命令列出的 VSZ) 是单个进程全部可访问的用户虚拟地址空间。其大小包括可能还尚未在内存中驻留的部分。比如地址空间已经被 malloc 分配,但是还没有实际写入。对于确定单个进程实际内存使用大小, VSS 用处不大。VSS为进程所有vma段大小之和,包括常规内存和特殊内存。所以当一个进程的VSS特别大时,可能有两种异常情况,通过检查进程的maps或者procmem,可以区分。
内存泄漏
或者不断的映射特殊内存但是不释放映射,从而导致进程虚拟空间耗尽
- RSS :
单个进程实际占用的内存大小。RSS 易被误导的原因在于, 它包括了该进程所使用的所有共享库的全部内存大小。对于单个共享库, 尽管无论多少个进程使用,实际该共享库只会被装入内存一次。对于单个进程的内存使用大小, RSS 不是一个精确的描述。而且不同的查看方式统计出来的RSS的值不一样(PSS,USS情况也是如此),详细的见之后章节介绍:
- cat /proc/pid/smaps, showmap pid。RSS,PSS,USS 均不包括特殊内存映射。
- procrank, procmem pid。 RSS,PSS,USS均包括特殊映射内存,但是大小并不是整个特殊映射的vma的大小;而是有物理页映射到用户空间的大小。
- ps, top(没有PSS和USS信息)(其RSS信息最小,只是get_mm_rss获取的,其范围比较窄,只包括了 mm信息中的MM_FILEPAGES+ MM_ANONPAGES)
- PSS:
不同于RSS,它只是按比例包含其所使用的共享库大小。例如, 三个进程使用同一个占用 30 内存页的共享库。 对于三个进程中的任何一个,PSS 将只包括 10 个内存页。PSS 是一个非常有用的数字,因为系统中全部进程以整体的方式被统计, 对于系统中的整体内存使用是一个很好的描述。如果一个进程被终止, 其PSS 中所使用的共享库大小将会重新按比例分配给剩下的仍在运行并且仍在使用该共享库的进程。此种计算方式有轻微的误差,因为当某个进程中止的时候, PSS 没有精确的表示被返还给整个系统的内存大小也就是说一个进程死掉后,并不一定能释放所有的PSS(但是最终可能会对PSS对应内存的释放带来影响)。计算的时候每个进程占的比例为page/page->mapcount。
- USS:(重点使用这个指标)
是单个进程的全部私有内存大小。亦即全部被该进程独占的内存大小。USS 是一个非常非常有用的数字, 因为它揭示了运行一个特定进程的真实的内存增量大小。
如果进程被终止, USS 就是实际被返还给系统的内存大小。USS 是针对某个进程开始有可疑内存泄露的情况,进行检测的最佳数字。
- Swap:
常规内存中,不常用的匿名page会被交换到swap分区。某个进程被交换出去的匿名页的大小就是Swap(包括在swap cache中的和真正交换到swap分区的都算)。
- Pswap:
模仿PSS的概念,因为每个匿名页可能会被多个进程使用。因此Swap 中的page按照目前还有多少进程使用它,按照比例分配得到pswap。
- Uswap: (重点使用这个指标)
模仿Uss的概念,私有的且被swap出去的内存的大小。
测试步骤
- 测试版本和准备
- user_debug版本(注,目前有部分代码强耦合,没有合入。因此先使用邮件指定的版本)。
- 如果不是原生软件,则为user_debug版本+该软件(不要装太多其它软件)。
- 烧写PAC第一次开机设置手机 显示à休眠à30分钟;
- 获取APP相关进程的名字(虽然有很多APP可能只有1个进程):
- 开机,在启动APP之前,执行adb shell命令:dumpsys meminfo;
- 启动APP之后,再次执行adb shell命令:dumpsys meminfo;
- 对比启动前后的进程信息,找到所有该APK对应的前台进程和后台服务进程,比如QQ就有前台进程:com.tencent.mobileqq,后台服务进程com.tencent.mobileqq:MSF。
- 但是不包括关联的HAL进程的内存使用,比如camera拍照时只用统计com.android.camera2的内存使用,而不用统计关联的HAL进程mediaserver和surfaceflinger的内存使用(这部分依赖HAL层的理论计算值)。
测试步骤
- 第2次(及之后)开机,连接上adb,在linux shell下执行,adb root命令,使得之后的adb shell均以root身份执行。
- 使用APP之前,开机解锁状态下,执行adb shell cat /d/ion/heaps/ion_heap_system > pre_app_memory_usage.txt; 记录原始数据。
- 使用APP,在认为内存消耗最大的场景时,在linux shell执行脚本:app_mem.sh com.tencent.mobileqq com.tencent.mobileqq:MSF > app_memory_usage.txt (注,进程之间以空格隔离), 获取原始数据。
数据处理
使用表格《Android APP memory.xlsx》处理pre_app_memory_usage.txt ,app_memory_usage.txt。
- 找到APP 进程0的原始数据,dumpsys meminfo细节见1.3.1节:
** MEMINFO in pid 3897 [com.android.gallery3d] **
填写到表格的如下部分, 黄色部分为需要填写的;而蓝色部分还有红色部分是自动计算出来的。
- 如果包含多个进程,则找到APP 进程1的原始数据,添加到表中的接下来几项中,最多支持共4个进程。
- 到表的第250 行,按照进程填写Mali内存。主要参考mali_mem。
Mali | |||||
Process Name | mali_mem | max_mali_mem | external_mem | ump_mem | dma_mem |
sum | 0 | 0 | 0 | 0 | 0 |
- 到表的第260 行,处理ION的内存信息(仅供参考)。从原始数据pre_app_memory_usage.txt中获取测试该APP之前的ION的内存使用。从原始数据app_memory_usage.txt中获取使用该APP过程中ION的内存使用。
- 在表的第234行,填写测试场景介绍。
数据分析:
- 常规内存:
所有相关进程总体上分析,以《Android APP memory.xlsx》第236行为准。详细介绍见:1.3.1.
-
- PSS列为没有swap出去的部分;
- Private Swap 为swaped的部分;
- 红色部分With swap为前两者之和,这个是占用值的绝对数量,这个最有价值。
- 特殊内存,Mali:
Mali | |||||
Process Name | mali_mem | max_mali_mem | external_mem | ump_mem | dma_mem |
sum | 0 | 0 | 0 | 0 | 0 |
其中max_mali_mem为历史峰值;而mali_mem为采样时刻的值。
- 特殊内存,ION:
参考差值.
进程内存信息
Dumpsys meminfo -a PID
该信息是对1.4节smaps信息进行归类处理后得到,是分析常规内存的最佳手段。
- Native Heap:所有Native 分配的堆,包括smaps里面的[heap]和[anon:libc_malloc]XXX 段。
- Dalvik Heap:所有java分配的堆,包括/dev/ashmem/dalvik-alloc space还有/dev/ashmem/dalvik-main space等等.
- 整体的进程的Memory信息,最有用的是这部分;原生的计算是不包括swap出去的部分的,因此我们添加了patch来统计这些部分。需要用1.2.3节提到的表格处理一下。
- 一些较为详细的信息如下表介绍:
各项指标意义如下:
- 基本上RSS = Shared Dirty + Private Dirty + Shared Clean + Private Clean;
- PSS = Pss Total
- USS = Private Dirty + Private Clean.
Procrank
该项数据内容有限,仅供有限参考。
整体的内存信息:
shell@scx35_sp7731gea:/proc/153 # procrank
PID Vss Rss Pss Uss Swap PSwap cmdline
153 59636K 5352K 2293K 1540K 704K 704K /system/bin/surfaceflinger
1745 335012K 12296K 2863K 2148K 14976K 3665K com.tmall.wireless
但该命令会在用户空间处理所有进程的页表信息,相当占用CPU。而且RSS,PSS,USS均包括特殊映射内存。
Procmem PID
仅供有限参考。
可以认为是procrank信息的细化;多了4个clean,dirty信息。从这里可以看出,procrank和Procmem的RSS,PSS,USS均包括特殊映射内存,但是大小并不是整个特殊映射的vma的大小
- ShCl :shared且是clean的page
- ShDi:shared且是dirty的page
- PrCl:进程私有且clean的page
- PrDi:进程私有且dirty的page
shell@scx35_sp7731gea:/proc/153 # procmem 153
Vss Rss Pss Uss ShCl ShDi PrCl PrDi Name
------- ------- ------- ------- ------- ------- ------- -------
2028K 4K 4K 4K 0K 0K 4K 0K anon_inode:dmabuf
8K 0K 0K 0K 0K 0K 0K 0K
4K 0K 0K 0K 0K 0K 0K 0K
1012K 4K 4K 4K 0K 0K 4K 0K [stack:1173]
4052K 4K 4K 4K 0K 0K 88K 0K anon_inode:dmabuf
25 12K 12K 4K 0K 12K 0K 0K 0K /system/lib/egl/libEGL_mali.so
4K 4K 4K 4K 0K 0K 4K 0K /system/lib/egl/libEGL_mali.so
4K 0K 0K 0K 0K 0K 0K 0K /system/lib/egl/libEGL_mali.so
6K 0K 0K 0K 0K 0K 0K 0K /dev/mali0
4K 4K 4K 4K 0K 0K 4K 0K /system/bin/surfaceflinger
4K 0K 0K 0K 0K 0K 0K 0K /system/bin/surfaceflinger
4K 0K 0K 0K 0K 0K 0K 0K
568K 340K 340K 340K 0K 0K 276K 64K [heap]
132K 8K 8K 8K 0K 0K 8K 0K [stack]
0K 0K 0K 0K 0K 0K 0K 0K [vectors]
2028K 128K 118K 116K 12K 0K 724K 0K anon_inode:dmabuf (ION对应的)
2028K 128K 118K 116K 12K 0K 724K 0K anon_inode:dmabuf
6076K 804K 312K 132K 672K 0K 132K 0K /dev/graphics/fb0
特殊映射内存,但是大小并不是整个特殊映射的vma的大小。而且这里的大小和Mali那里统计出来的对应不上,偏小(还需要mali的同学一起研究; 因此目前以mali那边的内存统计为准)。anon_inode:dmabuf(ION)之和也明显小于运行某个APP之前和之后的ION之差值。
特殊内存信息
进程的特殊内存信息,依赖于其使用到的各个内核模块提供,如果没有就只能去扒smaps了(但是这样看不出share的);MEM来源可以是:
- 预留的物理内存,直接mmap到用户进程空间,比如framebuffer的mem;
- 预留的物理内存,通过ION等内核模块分配,并mmap到用户进程空间。
- 使用buddy系统的mem page,通过ION/mali等内核模块分配,并mmap到用户进程空间。
Mali
Mali模块的debugfs信息能看到各个进程使用的mali分配的mem的总和,这些和smaps等信息里面name为/dev/mali0的所有虚拟空间之和相等(因此说明这部分内存不会在各个进程中share)。5.1上目前大多数版本信息如下,会更丰富一些(而T8等的mali版本的内存信息要更简单得多)。
root@sp9830aea_5m_h100:/ # cat /sys/kernel/debug/mali0/gpu_memory
Name (:bytes) pid mali_mem max_mali_mem external_mem ump_mem dma_mem
==============================================================================================================
RenderThread 900 1835008 2621440 0 0 2359296
RenderThread 742 1572864 3858432 0 0 2654208
RenderThread 1032 6553600 6815744 0 0 8929280
surfaceflinger 163 786432 1310720 9842688 0 10145792
Mali mem usage: 10747904 //进程实际使用的之和
Mali mem limit: 1073741824
Mali mem os: 11272192 //进程实际分配的,因为其也有一个小缓存的,并不一定全部是进程用着
Mali mem page: 139264 //mali mmu的管理开销
某一个时刻某进程占用的mali 内存,参见 mali_mem项。
ION(multi-media,gralloc)
显示使用的ION内存情况,但是这些ion_buffer可能是多个进程共享的不能直接计算到某个进程的头上。只是上面记录的进程分配的而已。
因此要想知道哪个进程使用了多少ION内存,很难像普通内存和mali内存一样直接可以看出来。只能是大概记录启动某个APP之前,之中,之后的ION total值的变化。
比如 APP ION 内存使用 = 使用中ION值 - 使用前ION值 = 使用中ION值 - 使用后ION值。但是这些值均不太准确,最好是有理论上的计算公式。
root@sp7731c_1h10:/ # cat /d/ion/heaps/io
ion_heap_carveout_mm ion_heap_carveout_overlay ion_heap_system
at /d/ion/heaps/ion_heap_system <
client pid tid size alloc_time
----------------------------------------------------------
surfaceflinger 204 204 1642496 2012.1.1-3:28:58.322777 这里体现的是分配这个ION buffer的进程,而不是所
surfaceflinger 204 204 1642496 2012.1.1-3:28:58.285301 所有使用这个buffer的客户
surfaceflinger 204 204 1642496 2012.1.1-3:28:58.341728
surfaceflinger 204 204 1642496 2012.1.1-3:28:58.655235
surfaceflinger 204 204 3686400 2012.1.1-0:16:6.12969
surfaceflinger 204 204 1642496 2012.1.1-3:29:3.470695
surfaceflinger 204 204 1642496 2012.1.1-3:27:56.276939
surfaceflinger 204 204 1642496 2012.1.1-3:27:56.281669
surfaceflinger 204 204 1642496 2012.1.1-3:27:56.284324
surfaceflinger 204 204 1642496 2012.1.1-3:27:56.283195
----------------------------------------------------------
orphaned allocations (info is from last known client):
surfaceflinger 204 204 69632 0 1 2012.1.1-3:27:46.773094
surfaceflinger 204 353 1642496 0 1 2012.1.1-3:28:58.293785
surfaceflinger 204 474 6815744 0 1 2012.1.1-0:15:51.868164
----------------------------------------------------------
total orphaned 8527872
total 1226996736 关注该值即可
deferred free 0
----------------------------------------------------------
0 order 8 highmem pages in uncached pool = 0 total
0 order 8 lowmem pages in uncached pool = 0 total
0 order 4 highmem pages in uncached pool = 0 total
30 order 4 lowmem pages in uncached pool = 1966080 total
0 order 0 highmem pages in uncached pool = 0 total
23 order 0 lowmem pages in uncached pool = 94208 total
0 order 8 highmem pages in cached pool = 0 total
2 order 8 lowmem pages in cached pool = 2097152 total
8 order 4 highmem pages in cached pool = 524288 total
9 order 4 lowmem pages in cached pool = 589824 total
48 order 0 highmem pages in cached pool = 196608 total
0 order 0 lowmem pages in cached pool = 0 total
进程地址空间信息
1.3和1.4节的数据为整体信息,而详细的每一个虚拟空间的信息,可以根据本节查看。
下述统计中RSS,PSS,USS 均不包括特殊内存映射。这些信息会显示进程每个虚拟地址空间段的地址。
/proc/pid/smaps
这个是对进程地址空间以及内存使用,最全面的展示。
如果打开了我们优化后的MORE_SMAPS_INFO 开关(默认user_debug版本就有),信息会更丰富,Dumpsys meminfo PID和showmap PID原始数据均来之与smaps;然后进行了归类处理。
6f387000-6ff18000 rw-p 00000000 b3:15 7575 /data/dalvik-cache/arm/system@framework@boot.art
Size: 11844 kB 该段虚拟空间大小
Rss: 11828 kB = Shared_Clean+ Shared_Dirty+ Private_Clean+ Private_Dirty= Filecache+ Anonymous
Pss: 2179 kB = Pss_Filecache+ Pss_Anonymous
Uss: 1304 kB = Private_Filecache+Private_Anonymou
Shared_Clean: 7964 kB 和其它进程共享而且是干净的
Shared_Dirty: 2560 kB 和其它进程共享而且是脏的
Private_Clean: 616 kB 本进程私有而且是干净的
Private_Dirty: 688 kB 本进程私有而且是脏的
Referenced: 11544 kB
Filecache: 8580 kB 文件缓存 = Shared_Filecache+ Private_Filecache
Pss_Filecache: 1344 kB 按比例共享的文件缓存
Shared_Filecache: 7964 kB 多进程共享的文件缓存
Private_Filecache: 616 kB 私有的文件缓存
Anonymous: 3248 kB 匿名内存 = Shared_Anonymous+ Private_Anonymous
Pss_Anonymous: 835 kB 按比例共享的匿名内存
Shared_Anonymous: 2560 kB 多进程共享的匿名内存
Private_Anonymous: 688 kB 私有的匿名内存
AnonHugePages: 0 kB
Swap: 0 kB 进程被交换出去的匿名页
PSwap: 0 kB 按比例共享的被交换出去的匿名页
USwap: 0 kB 私有的被交换出去的匿名页
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac mg
下面以surfaceflinger进程为例:
- 映射普通文件:
该段虚拟空间进程空间地址 只读可执行 用途
b6525000-b6627000 r-xp 00000000 b3:11 724 /system/lib/libMali.so
Size: 1032 kB 这段虚拟空间大小
Rss: 564 kB
Pss: 170 kB
Shared_Clean: 516 kB
Shared_Dirty: 0 kB
Private_Clean: 48 kB
Private_Dirty: 0 kB
Referenced: 564 kB
Anonymous: 0 kB 匿名页大小
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd ex mr mw me mg 这段虚拟地址的属性
- Java相关:
这些比较有意思,同样一段地址包含有anon还有文件cache:
6f387000-6ff18000 rw-p 00000000 b3:15 7575 /data/dalvik-cache/arm/system@framework@boot.art
Size: 11844 kB
Rss: 11828 kB
Pss: 2179 kB
Uss: 1304 kB
Shared_Clean: 7964 kB
Shared_Dirty: 2560 kB
Private_Clean: 616 kB
Private_Dirty: 688 kB
Referenced: 11544 kB
Filecache: 8580 kB
Pss_Filecache: 1344 kB
Shared_Filecache: 7964 kB
Private_Filecache: 616 kB
Anonymous: 3248 kB
Pss_Anonymous: 835 kB
Shared_Anonymous: 2560 kB
Private_Anonymous: 688 kB
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
USwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac mg
- 堆和栈
b80fe000-b8197000 rw-p 00000000 00:00 0 [heap]
Size: 612 kB
Rss: 412 kB
Pss: 412 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 412 kB
Referenced: 404 kB
Anonymous: 412 kB
AnonHugePages: 0 kB
Swap: 200 kB
PSwap: 200 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac
5.0以后典型堆如下:
b5000000-b5200000 rw-p 00000000 00:00 0 [anon:libc_malloc]
Size: 2048 kB
Rss: 1048 kB
Pss: 645 kB
Uss: 600 kB
Shared_Clean: 0 kB
Shared_Dirty: 448 kB
Private_Clean: 0 kB
Private_Dirty: 600 kB
Referenced: 904 kB
Filecache: 0 kB
Pss_Filecache: 0 kB
Shared_Filecache: 0 kB
Private_Filecache: 0 kB
Anonymous: 1048 kB
Pss_Anonymous: 645 kB
Shared_Anonymous: 448 kB
Private_Anonymous: 600 kB
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
USwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac mg
be86a000-be88b000 rw-p 00000000 00:00 0 [stack]
Size: 136 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 12 kB
PSwap: 12 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
- 特殊映射
可以看到这些用户进程虚拟区域的RSS,PSS等都是0,而且vmflags包含pf。说明其是物理内存映射的特殊的内存。只要是映射,就可能会在多个进程中shared。
映射来至设备文件fb0的内存。
b5d1c000-b630b000 rw-s 00000000 00:0c 533 /dev/graphics/fb0
Size: 6076 kB
Rss: 0 kB 是0
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr sh mr mw me ms pf io de dd
映射来至ION分配的graphic内存(gralloc+ion)。但是在Ion的信息里面不一定能看见是谁分配了。
b5517000-b5712000 rw-s 00000000 00:08 3944 anon_inode:dmabuf
Size: 2028 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr sh mr mw me ms pf io de dd
映射来至mali分配的内存。目前看来smaps所有的/dev/mali0的mem之和跟mali那边统计的信息是一致的。
b4fdc000-b501c000 rw-s 00400000 00:0c 6264 /dev/mali0
Size: 256 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
PSwap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr sh mr mw me ms pf io de dd
- 各段数据之和总计
Rss_All: 57980 kB
Pss_All: 18991 kB
Uss_All: 14004 kB
Rss_Filecache_All: 33168 kB
Rss_Anonymous_All: 24772 kB
Pss_Filecache_All: 7257 kB
Pss_Anonymous_All: 11732 kB
Uss_Filecache_All: 3324 kB
Uss_Anonymous_All: 10680 kB
Swap_All: 0 kB
Pswap_All: 0 kB
USwap_All: 0 kB
Showmap PID
将smaps的信息按照object进行了归集,然后还按照类别进行了组织,供参考。
shell@scx35_sp7731gea:/proc/153 # showmap 153
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
128 28 0 0 28 0 0 1 /dev/__properties__
1016 4 4 0 0 4 0 1 /dev/binder
12152 0 0 0 0 0 0 2 /dev/graphics/fb0
1280 0 0 0 0 0 0 5 /dev/mali0
68 44 5 40 0 0 4 3 /system/bin/linker
8 4 4 0 0 4 0 2 /system/bin/surfaceflinger
20 16 8 12 0 0 4 3 /system/lib/egl/libEGL_mali.so
32 28 18 20 0 4 4 3 /system/lib/egl/libGLESv1_CM_mali.so
28 20 8 20 0 0 0 3 /system/lib/egl/libGLESv2_mali.so
48 28 18 12 0 8 8 5 /system/lib/hw/gralloc.sc8830.so
92 84 84 0 0 76 8 4 /system/lib/hw/hwcomposer.sc8830.so
24 8 6 4 0 0 4 5 /system/lib/hw/power.default.so
20 12 12 0 0 12 0 3 /system/lib/hw/sprd_gsp.sc8830.so
340 104 37 84 0 0 20 4 /system/lib/libEGL.so
316 152 38 152 0 0 0 4 /system/lib/libGLES_trace.so
28 20 6 16 0 4 0 3 /system/lib/libGLESv1_CM.so
36 24 4 24 0 0 0 4 /system/lib/libGLESv2.so
1064 692 242 604 0 76 12 4 /system/lib/libMali.so
196 172 23 160 0 0 12 3 /system/lib/libbinder.so
364 220 29 196 0 0 24 4 /system/lib/libc.so
20 4 0 4 0 0 0 3 /system/lib/libcorkscrew.so
48 44 9 36 0 0 8 4 /system/lib/libcutils.so
24 12 1 12 0 0 0 3 /system/lib/libgabi++.so
28 4 0 4 0 0 0 4 /system/lib/libgccdemangle.so
256 236 68 204 0 8 24 4 /system/lib/libgui.so
12 4 0 4 0 0 0 3 /system/lib/libhardware.so
1248 312 34 312 0 0 0 4 /system/lib/libicui18n.so
1016 184 20 184 0 0 0 4 /system/lib/libicuuc.so
12 4 0 4 0 0 0 3 /system/lib/libion.so
20 20 8 12 0 0 8 3 /system/lib/liblog.so
108 60 15 52 0 0 8 4 /system/lib/libm.so
328 20 1 20 0 0 0 4 /system/lib/libsqlite.so
12 8 4 4 0 0 4 3 /system/lib/libstdc++.so
212 104 8 104 0 0 0 3 /system/lib/libstlport.so
204 176 176 0 0 148 28 5 /system/lib/libsurfaceflinger.so
12 8 4 4 0 0 4 3 /system/lib/libsync.so
44 44 13 36 0 0 8 3 /system/lib/libui.so
88 80 11 72 0 0 8 4 /system/lib/libutils.so
160 0 0 0 0 0 0 25 [anon]
568 340 340 0 0 0 340 1 [heap]
4 4 0 4 0 0 0 1 [sigpage]
1012 4 4 0 0 0 4 1 [stack:1173]
1012 4 4 0 0 0 4 1 [stack:255]
1012 4 4 0 0 0 4 1 [stack:256]
1012 4 4 0 0 0 4 1 [stack:261]
1012 4 4 0 0 0 4 1 [stack:290]
1012 4 4 0 0 0 4 1 [stack:291]
1012 0 0 0 0 0 0 1 [stack:304]
1012 4 4 0 0 0 4 1 [stack:305]
1012 0 0 0 0 0 0 1 [stack:306]
1012 0 0 0 0 0 0 1 [stack:316]
1012 4 4 0 0 0 4 1 [stack:317]
1012 4 4 0 0 0 4 1 [stack:320]
1012 4 4 0 0 0 4 1 [stack:322]
1012 4 4 0 0 0 4 1 [stack:323]
1012 4 4 0 0 0 4 1 [stack:647]
136 8 8 0 0 0 8 1 [stack]
4 0 0 0 0 0 0 1 [vectors]
22640 0 0 0 0 0 0 14 anon_inode:dmabuf
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
59644 3384 1314 2416 28 344 596 188 TOTAL
进程的内存使用优化
仅供参考,需要所有APP Owner 积累/share经验。
Managing your App's Memory
http://developer.android.com/training/articles/memory.html
http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html
http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html
http://android-developers.blogspot.com/2009/02/track-memory-allocations.html
http://tools.android.com/recent/lintperformancechecks
比如:
- Java heap:
对应于dalvik/ART虚拟机使用的内存,实际上一般应用发生OOM时,大家都会想到使用
Hprof文件进行分析,这个Hprof 就是 dump java heap得来的,真实反映了Java heap的使用情况,对象种类等,
实际上,dump heap不是说只能在OOM时进行,虚拟机提供了调试接口给一些工具帮助分析内存,比较适合当前
分析Java heap的情况,我们可以在APP的不同场景下,抓取对应的hprof进行分析,比如哪些对象的内存使用
可能是不恰当的,或者不需要的,以达到优化的目的。
对应的工具有:Eclipse可以在调试的时候dump heap;Studio应该也是有这个功能的
heap分析工具:MAT(Mem analysis tool)
sdk中的工具:hprof-converter
- Mali内存占用多:
能否牺牲一些GPU的效果??
- Code段占用内存太多:
能否缩小APK,.so的大小?
- Native 内存占用过多:
见文档《Android Native Memory Leakage Debug Guide.docx》。