android内存分析
本文主要介绍
- 操作系统的内存管理部分知识
- 执行命令 adb shell dumpsys meminfo [进程名] 得到信息的相关分析
- private dirty
- private clean
- RSS
- PSS
- Swap pss
前置知识
操作系统的内存管理
- 一个进程的实际数据存在RAM(内存)和ROM(存储空间)。之所以需要再ROM里存储是因为RAM是稀缺资源。
- 为了安全考虑,面向用户的往往是虚拟地址,从虚拟地址查找实际物理地址,需要层层查找,类似GLIDE。查找这个过程需要TLB,基址来决定。
- TLB理解为索引表即可, 也可以理解为缓存。查找地址的复杂度为O(1)
- 如果索引没找到,通过基址 + offset查找,复杂度为O(n)
- 如果还没找到,只能通过IO去硬盘找
- 硬盘这部分空间,往往称为交换(swap)空间
- 另外为了防止进程内存无限膨胀(比如),需要设置驻留集(Resident Set Size),下面对驻留集进行了介绍
- 驻留集(Resident Set Size)
- 给每个进程分配特定大小的常驻空间
- 驻留集分为可变驻留集和固定驻留集
- 可变驻留集
- 缺页率较高,需要变化
- 比较复杂,要求操作系统评估活动进程行为,不过对于当前的操作系统来讲 基操勿6
- 增加软件开销
- 依赖硬件
- 固定驻留集
- 如果驻留集满了,需要将部分Page(这里理解为内存)换到硬盘空间,如下图,page1被交换到硬盘空间了
- 当进程需要page1的时候,从硬盘空间交换到内存里。此时硬盘空间和内存均有数据(注意硬盘中的page1大部分情况不会被清理)。如果就出现了缓存模型,会有缓存失效等问题。
- 当后续进程改动了page1,此时这块内存就叫Dirty Page,如果想交换Dirty Page到硬盘,需要重新对硬盘地址进行IO。因为被修改了,映射关系会变。
- 反之没有被改动的内存称为**Clean page,**如果想抹掉clean page,直接抹掉clean page内存即可。而无需关心硬盘地址。
dump内存分析
执行命令 adb shell dumpsys meminfo [进程名], 可以得到如下信息
kotlin
Applications Memory Usage (in Kilobytes):
Uptime: 2051700 Realtime: 2051700
** MEMINFO in pid 3049 [com.joyzhou.demo] **
Pss Private Private SwapPss Rss Heap Heap Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 19028 18676 276 1312 23092 28672 18478 5400
Dalvik Heap 23190 22872 148 0 31176 29253 4677 24576
Dalvik Other 3854 2680 272 372 6092
Stack 984 816 168 500 996
Ashmem 80 0 0 0 928
Other dev 20 0 20 0 332
.so mmap 1756 252 792 0 38040
.jar mmap 1051 0 0 0 33092
.apk mmap 542 0 4 0 1464
.dex mmap 8749 0 8744 29240 9244
.oat mmap 52 0 0 0 2740
.art mmap 2832 2064 472 3668 16336
Other mmap 195 8 140 0 1760
Unknown 331 160 140 108 2128
TOTAL 97864 47528 11176 35200 167420 57925 23155 29976
App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 25408 47512
Native Heap: 18676 23092
Code: 9792 86416
Stack: 816 996
Graphics: 0 0
Private Other: 4012
System: 39160
Unknown: 9404
TOTAL PSS: 97864 TOTAL RSS: 167420 TOTAL SWAP PSS: 35200
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 5 Activities: 0
Assets: 8 AssetManagers: 0
Local Binders: 23 Proxy Binders: 41
Parcel memory: 13 Parcel count: 52
Death Recipients: 6 OpenSSL Sockets: 0
WebViews: 0
SQL
MEMORY_USED: 577
PAGECACHE_OVERFLOW: 180 MALLOC_SIZE: 46
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 96 57 180/161/25 /data/user/0/com.pvr.pvrfit/no_backup/androidx.work.workdb
4 8 0/0/0 (attached) temp
4 96 40 7/31/4 /data/user/0/com.pvr.pvrfit/no_backup/androidx.work.workdb (2)
4 48 51 7/95/9 /data/user/0/com.pvr.pvrfit/databases/com_picovr_fit_database.db
4 16 0/0/0 (attached) temp
4 48 82 222/32/5 /data/user/0/com.pvr.pvrfit/databases/com_picovr_fit_database.db (3)
下面解释几个比较难理解概念
- PSS (Proportional Set Size): Proportional翻译为比例化的。实际使用的物理内存。平时使用一般看这个
- SwapPss: 硬盘中的交换空间大小
- RSS (Resident Set Size): 驻留集大小,android采用的是可变驻留集。这块有部分共享内存占用
- Private Clean: 没有被更改的内存,踢出clean page,直接抹掉clean page内存即可。而无需关心硬盘地址
- Private Dirty:被更改的内存,踢出Dirty Page,需要重新对硬盘地址进行IO。因为被修改了,映射关系会变
- Code: 代码的内存占用
- Graphics: 表示图形相关内存占用
- System: 表示系统相关的内存,这个部分每个系统逻辑策略不一样,比如ard10较小,ard12较大。
另外再Objects中可以发现一些内存泄漏的相关信息,比如ViewRootImpl, Activities等