1.内存指标
Item | 全称 | 含义 | 等价 |
---|
USS | Unique Set Size | 物理内存 | 进程独占的内存 | PSS | Proportional Set Size | 物理内存 | Pss =Uss+按比例包含共享库 | RSS | Resient Set Size | 物理内存 | RSS=USS+包含共享库 | VSS | Virtual Set Size | 虚拟内存 | VSS = RSS+未分配实际物理内存 |
内存的大小关系:VSS>RSS>=PSS>=USS 在实际分析中,一般是以PSS的内存为准,且也是最符合实际情况的统计值
2.使用
可以使用以下命令记录应用内存在不类型的RAM分配之间的划分情况
adb shell dumpsys meminfo package_name|pid [-d]
-d 标记会输出更多与Dalvik和ART内存占用情况相关的信息。 输出列出了应用当前实时的优点分配信息,以千字节(K)为单位。
- 获取全局的内存信息
除了通过上面的方式获取单个进程的内存信息,还可以获取系统整体内存情况。主要场景是用于确认单应用多进程的场景,对比下其他进程的当前内存状态,以及进程状态,我们要确保进程处理合理的状态。(比如UI进程退到后台要及时退到Cache状态,处于其他状态则要进行优化)
Total PSS by OOM adjustment:
683,512K: Native
...
854K: dumpsys (pid 19280)
851K: lmkd (pid 789)
843K: android.hardware.memtrack@1.0-service (pid 748)
...
396,026K: System
396,026K: system (pid 1597)
666,050K: Persistent
...
253,989K: com.android.systemui (pid 2326)
46,482K: com.huawei.systemserver (pid 2588)
40,122K: com.huawei.hiview (pid 2543)
...
47,613K: Persistent Service
34,164K: com.android.bluetooth (pid 20268)
475,283K: Foreground
242,908K: com.huawei.android.launcher (pid 10760 / activities)
351,023K: Visible
127,248K: com.huawei.hwid.core (pid 28223)
...
117,719K: Perceptible
95,123K: com.baidu.input_huawei (pid 6331)
...
150,336K: A Services
82,429K: com.huawei.health:DaemonService (pid 16676)
196,753K: Previous
159,932K: com.android.mms (pid 16921 / activities)
...
527,396K: B Services
164,049K: com.tencent.mm (pid 15990)
...
1,177,708K: Cached
139,752K: com.huawei.health (pid 18841)
...
3.各个属性的详解
3.1 实际样例
以微信举例,如下是一个完整的微信进程的meminfo信息
>adb shell "dumpsys meminfo com.tencent.mm -d"
Applications Memory Usage (in Kilobytes):
Uptime: 539705041 Realtime: 772532637
** MEMINFO in pid 15990 [com.tencent.mm] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 7697 7688 0 38401 69632 56969 12662
Dalvik Heap 7223 7220 0 5540 12964 9723 3241
Dalvik Other 2277 2276 0 4570
Stack 36 36 0 20
Ashmem 2 0 0 0
Other dev 21 0 20 0
.so mmap 41972 4032 25560 35
.jar mmap 1245 0 0 0
.apk mmap 51193 0 13360 0
.ttf mmap 681 0 0 0
.dex mmap 5332 28 704 352
.oat mmap 510 0 0 0
.art mmap 16366 15940 0 11369
Other mmap 3672 512 464 0
GL mtrack 2272 2272 0 0
Unknown 1848 1848 0 3731
TOTAL 206365 41852 40108 64018 82596 66692 15903
App Summary
Pss(KB)
------
Java Heap: 23160
Native Heap: 7688
Code: 43684
Stack: 36
Graphics: 2272
Private Other: 5120
System: 124405
TOTAL: 206365 TOTAL SWAP PSS: 64018
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 5 Activities: 0
Assets: 8 AssetManagers: 0
Local Binders: 77 Proxy Binders: 84
Parcel memory: 34 Parcel count: 142
Death Recipients: 8 OpenSSL Sockets: 0
WebViews: 0
SQL
MEMORY_USED: 376
PAGECACHE_OVERFLOW: 57 MALLOC_SIZE: 117
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 28 35 2/18/3 /data/user/0/com.tencent.mm/databases/Scheduler.db
4 108 109 26/30/15 /data/user/0/com.tencent.mm/databases/google_app_measurement.db
Asset Allocations
: 8000K
3.2数据来源
3.2.1 dumpsys 实现逻辑简单介绍
dumpsys的源码结构其实很简单,只有一个dumpsys.cpp 源码路径是:/frameworks/native/cmds/dumpsys/dumpsys.cpp 在其main方法中,先通过defaultServiceManager()函数获得ServiceManager对象,然后根据dumpsys传进来的参数通过函数checkService来找到具体的service,并执行service的dump方法,达到dumpsys meminfo的目的。
3.2.2 dumpsys meminfo的数据来源
dumpsys meminfo 对应的服务是ActivityManagerService,它从MemBinder类的dump函数开始执行的。总结来说不同类型的Meminfo信息是从不同的位置获取的 ![在这里插入图片描述](https://img-blog.csdnimg.cn/843bae2df89e4b4a9f3cfd81730c2b7a.png
3.3 属性值详解
3.3.1 主要属性值价绍
我们先从横坐标开始:
序号 | 字段名称 | 解释 |
---|
1 | Pss Total | Pss是指实际使用的物理内存,考虑了在进程之间共享RAM页的情况。进程独占的RAM页会直接计入其PSS值,而与其他进程共享的RAM页则会按相应比例计入PSS值。例如,两个进程之间共享的RAM页会将其一半的大小 分别计入这两个进程的PSS中, Pss Total 就是指某一项Pss的总值。 | 2 | Private Dirty | 进程私有,是仅分配给应用堆的实际RAM,包含了您自己的分配和zygote分配页,这些分配页自从zygote派生您的应用进程以来已被修改。 | 3 | Private Clean | 进程私有的,相对磁盘数据没有使用修改的内存。 | 4 | SwapPss Dirty | 一些Android设备确实使用了内存交换,但它们使用的是内存而不是闪存。Linux有一个称为ZRAM的特性,它可以压缩页面,然后将它们交换到一个特殊的RAM区域,并在需要时再次解压它们。因此,“交换肮脏”中列出的页面很可能是在ZRAM中。 |
纵坐标
序号 | 属性名 | 说明 |
---|
1 | Native Heap | 在Native Code中使用malloc分配出的内存 | 2 | Dalvik Heap | Dalvik 虚拟机(Java 代码)分配的空间,不包括它自身的开销,Dalvik堆中和zygote进程共享的部分算是sharedDirty | 3 | Dalvik Other | 类数据结构和索引占据的内存 | 3 | Stack | 堆内存 | 4 | Ashmem | 匿名共享内存,此类内存与cache shrinker关联,可以控制cache shrinker在适当时机回收这些共享内存 | 5 | Other dev | 内存drvier占用的内存 | 6 | .so mmap | 映射的.so(native) 占用的内存 | 7 | .jar mmap | Java文件代码占用内存 | 8 | .apk mmap | apk代码占用内存 | 8 | .dex mmap | 映射的.dex(Dalvik 或ART)代码占用的内存 | 9 | .oat mmap | 代码映射占用的RAM量。此映像在所有应用之间共享,不受特定应用影响 | 10 | .art mmap | 堆映像占用的RAM量,此映像在所有应用之间共享,不受特定应用影响。尽管ART映射包含Object实例,它仍然不会计入您的堆大小 | 11 | other mmap | 其他文件占用的内存 |
- 我们某个进程实际的Pss 代码实际内存大小是指横坐标为Pss Total,纵列为Total值(其值等于Pss Total 列+SwapPss Dirty 列的总和),如上所示微信总内存为
206365 K. - .art mmap 和.dex mmap 列的详细信息可以通过
showmap pid (其他是通过解析/proc/pid/smaps 来得到的结果,详细见待整理)来获取更详细的信息,meminfo里面的信息其实也是smaps通过后缀名来统计各类的mmap值。
3.3.2 Heap相关
| Heap Size | Heap Alloc | Heap Free |
---|
Native Heap | Native Code 使用malloc分配的堆内存总大小,从mallinfo usmblks获得,代表最大总共分配空间 | 从mallinfo uorblks获得,总共已分配空间 | 从mallinfo fordblks获得,代表总共剩余空闲空间 | Dalvik Heap | 虚拟机分配的堆内存总大小,从Runtime totalMemory()获得,Dalvik Heap总共的内存大小 | Runtime Total Memory()-freeMemory(),Dalvik Heap已分配的内存大小 | 从RunTime freeMemory获得,Dalvik Heap剩余的内存大小 |
3.3.3 Objects
- ViewRootImpl
进程中当前处于活动状态的根视图数量。每个根视图都与一个窗口关联,因此该值有助于您确实与对话框或者其他窗口有关的内存泄漏 - AppContexts 和 Activities
您的进程中当前处于活动状态的应用 Context 和 Activity 对象数量。该值可以帮助您快速确定发生泄漏的 Activity 对象,这些对象由于存在对其的静态引用(比较常见)而无法进行垃圾回收。这些对象往往关联了许多其他分配,因此是查找大型内存泄漏的理想工具。当通过Back不断返回退出应用时,Activities值应该等于1
注意 在包含Delvik other 区段的更高平台上,Delvik堆的Pss Total和private Dirty数值不包括Dalvik开销(例如即时编译(JIT和垃圾回收记录)),而更低的版本会在Dalvik中将会其一并列出。
4. 参考资料
https://www.jianshu.com/p/9edfe9d5eb34 https://developer.android.google.cn/studio/command-line/dumpsys#meminfo
|