一、内存相关
参考Android内存分析命令_dumpsys meminfo 算出rss-CSDN博客
1、基本概念
1)PSS & RSS & USS & VSS
a、PSS
- 概念:全称Proportional Set Size,根据进程实际使用的内存量按照共享比例分配给进程的一种内存度量方式。如果多个进程共享同一块内存页,那么共享的内存会被均摊到各个进程的 Pss 中,以更准确地反映各个进程实际使用的内存。
- 意义:根据共享比例分配内存的方式,因此相比于简单的内存统计,它提供了更精确的内存使用情况,避免重复计算共享内存,更好地反映进程真实的内存占用情况。
b、RSS
- 概念:全称Resident Set Size,指示一个进程当前在物理内存中占用的实际大小,包括私有页和共享页的总和。这表示了一个进程实际占用了多少物理内存资源。
- 意义:更加直接地表示了一个进程当前占用的物理内存大小,包括私有页和共享页。通过监控 Rss,可以了解一个进程实际消耗的系统资源,帮助识别内存泄漏、优化内存使用等问题。
2)Dirty & Clean & SwapPss
a、Private Dirty
- 概念:表示进程私有页中已经修改(脏数据)的内存量。这些数据是进程独占并且已被修改的,通常表示进程对这部分内存执行了写入操作
- 意义:Private Dirty占比过高,可能意味着进程频繁地修改内存数据,导致系统产生大量的脏页,增加了写入操作的开销。优化这部分内存的管理,减少不必要的写入操作,可以提高系统性能
b、Private Clean
- 概念:表示进程私有页中未被修改(干净数据)的内存量。这些数据是进程独占但未被修改的,通常表示这部分内存没有发生写入操作。
- 意义:Private Clean 有助于了解进程对内存的读取操作情况和内存使用效率。较高的 Private Clean 可能暗示着进程大量读取数据但很少进行写入操作,即访问模式偏向读取而不是写入。
c、SwapPss Dirty
- 概念:用于监视系统中内存交换操作的情况。当系统内存不足时,操作系统会将部分内存页交换到磁盘的交换空间以腾出物理内存供其他程序使用。
- 意义:SwapPss 提供了一个指标,用于监视系统中内存交换操作的情况。当系统内存不足时,操作系统会将部分内存页交换到磁盘的交换空间以腾出物理内存供其他程序使用。高 SwapPss 值通常暗示着系统内存不足,导致操作系统频繁地将内存页交换到磁盘上的交换空间,这可能会对系统性能产生负面影响。
- 作用:此值通常出现在dumpsys meminfo packagename命令里面
3)Swap & buffers & cache
a、Swap
- 概念:是一种操作系统用来缓解物理内存不足的机制。当系统的物理内存达到极限,而仍有进程需要更多内存时,操作系统会将不常用的内存页面移动到硬盘上的交换空间(Swap),以释放物理内存给那些需要更多内存的进程使用。交换空间通常位于硬盘上,并作为虚拟内存来扩展系统的内存容量。尽管交换空间能够帮助系统继续正常运行,但由于硬盘访问速度远慢于内存,因此使用交换空间会导致系统性能下降。因此,最好的情况是尽量避免频繁地使用交换空间,以确保系统能够在物理内存中运行。
- 作用:Swap实际上是一段占用在磁盘上的空间,他的主要用途如下:在物理内存RAM不足的时候操作系统将一些不常用的内存页从物理RAM移动到SWAP空间里面,这样将腾出更多的RAM空间运行其他活跃的进程;可以通过SWAP作为虚拟内存来扩展系统的内存容量,例如一些手机厂商定制的内存融合方案。
- 意义:如果swap的使用率比较高,说明当前系统物理内存RAM不足,个人理解这只是一个参考指标,因为在内存ram充足的时候也存在swap的使用,在扩展系统内存的方案里面也存在使用swap,因此通常需要发现问题的时候进行对比参考。
b、buffers
- 概念:用于临时存储数据的内存区域。当系统需要将数据从一个地方传输到另一个地方时,会使用缓冲区来暂时存储这些数据,以提高数据传输的效率。缓冲区通常用于处理I/O操作,比如磁盘读写、网络数据传输等。数据先被写入缓冲区,然后再由系统异步地将数据传输到目标位置,避免了频繁访问实际设备所带来的性能开销。
- 意义:buffers被分配在RAM中,主要针对IO/网络等其他场景下。
c、cache
- 概念:这里主要指的swap cache,指系统将交换空间(Swap)中的数据缓存到内存中,以便快速访问已经移至交换空间的数据。当系统发现某些数据频繁地被交换到交换空间中(因为物理内存不足等原因),为了提高这些数据的访问速度,系统会将这些数据缓存到内存中,这样下次访问这些数据时就可以更快地获取,而不必每次都从交换空间重新读取。
- 意义:swap cache同buffers一样,他也被分配在RAM中的一段缓存区,但不同的是swap cache里面的缓存数据是专门针对需要和swap交换的内存数据,而buffer里面的缓存数据可能被用于I/O读写/网络数据传输等其他各种场景(PS:个人理解)。
2、命令解读
1)dumpsys meminfo
此命令查询系统当前整体的内存状态,如下先打印了当前的时间搓
C:\Users\Administrator>adb shell dumpsys meminfo
Applications Memory Usage (in Kilobytes):
Uptime: 32351135 Realtime: 85587685
- Total RSS by Process:展示了系统当前各个进程的RSS使用情况,按照顺序排列
Total RSS by process:
1,203,384K: io.supercent.pizzaidle (pid 4810 / activities)
------> PS:此时的前台进程RSS占用1203M
250,004K: system (pid 1445)
160,036K: com.google.android.gms (pid 22458)
158,204K: com.android.systemui (pid 1804)
130,548K: surfaceflinger (pid 786)
127,192K: camerahalserver (pid 1076)
88,844K: com.google.android.gms.persistent (pid 16497)
88,076K: com.transsion.smartpanel (pid 8593)
83,160K: com.transsion.XOSLauncher (pid 5980 / activities)
............
- Total RSS by OOM adjustment:按照OOM调整的类别来进行展示
Total RSS by OOM adjustment:
848,928K: Native --->下面是native层的进程(包括系统和底层服务),总计848M
130,548K: surfaceflinger (pid 786)
127,192K: camerahalserver (pid 1076)
77,560K: android.hardware.graphics.composer@3.1-service (pid 729)
23,808K: zygote64 (pid 716)
14,396K: android.hardware.media.c2@1.2-mediatek-64b (pid 731)
.........
250,004K: System --->下面是系统进程(如system进程,注意systemui不算),总计250M
250,004K: system (pid 1445)
339,500K: Persistent -->持久性进程(如systemui)感觉像是配置了Persistent参数的进程
158,204K: com.android.systemui (pid 1804)
47,072K: com.android.phone (pid 2060)
40,340K: com.android.networkstack.process (pid 1925)
29,560K: com.mediatek.ims (pid 2025)
72,824K: Persistent Service -->持久性服务进程
37,052K: com.android.bluetooth (pid 21973)
35,772K: com.google.android.providers.media.module (pid 3149)
1,423,652K: Foreground --->前台进程(通常是用户当前与之交互的应用程序)
1,203,384K: io.supercent.pizzaidle (pid 4810 / activities) --->当前正在玩这个游戏
88,844K: com.google.android.gms.persistent (pid 16497)
71,740K: com.google.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0 (pid 5275)
59,684K: com.google.android.adservices.api (pid 3890)
962,372K: Visible --->可见进程(但是并没有操作的进程)
160,036K: com.google.android.gms (pid 22458)
88,076K: com.transsion.smartpanel (pid 8593)
194,036K: Perceptible --->这些进程是可察觉的,即用户可以感知到其活动或影响
54,924K: com.google.android.inputmethod.latin (pid 17551)
44,192K: com.transsion.kolun.assistant (pid 7307)
38,876K: com.google.android.apps.messaging:rcs (pid 16560)
28,088K: com.transsion.batterylab (pid 16564)
27,956K: com.transsion.uxdetector (pid 16570)
58,364K: Perceptible Medium -->这些进程也是可察觉的,但相对于 Perceptible 类别来说,它们的活动可能更为中等或轻微
58,364K: com.google.android.googlequicksearchbox:search (pid 3543)
46,896K: Backup -->备份进程,在某些情况下可能会执行备份操作
46,896K: com.transsion.plat.appupdate (pid 3056)
43,308K: Previous -->之前的进程,可能指在过去某个时间段内运行过的进程
43,308K: com.google.process.gservices (pid 32449)
181,300K: Cached -->缓存进程,一般用于存储最近使用过的数据或资源以提高访问速度
79,588K: com.hoffnung:remote (pid 6009)
51,536K: com.google.android.permissioncontroller (pid 5059)
50,176K: com.transsion.plat.appupdate.ui (pid 3305)
- Total RSS by category:按照类别(非进程的角度)来进行展示
Total RSS by category:
1,086,084K: .so mmap ->表示共有 1086M的内存用于动态链接库的内存映射操作
580,804K: GL mtrack ->代表图形库OpenGL内存追踪所占用的内存大小为 580M
466,792K: .art mmap ->表示用于 Android 运行时环境(ART)的内存映射占用
354,016K: EGL mtrack ->指 OpenGL ES 内存追踪占用了 354,016K 的内存量
351,796K: .jar mmap ->表示 Java 程序文件(.jar 文件)的内存映射使用量
313,896K: .oat mmap ->用于优化程序的可执行文件和数据缓存.oat 文件的内存映射
226,636K: Native -->表示本地代码进程所占用的内存
212,288K: Unknown ->未知类型的资源占用
187,164K: Dalvik -->Dalvik 虚拟机相关的资源消耗
181,812K: .apk mmap ->APK 文件的内存映射占用
148,348K: .dex mmap ->可执行文件.dex 文件的内存映射占用
130,448K: Other mmap ->其他类型的内存映射占用
86,284K: Dalvik Other ->Dalvik 虚拟机的其他资源消耗了 86,284K 的内存
70,496K: Other dev ->其他开发相关的资源占用
19,296K: Stack ->栈内存占用了 19,296K 的空间
4,844K: Ashmem ->匿名共享内存(Ashmem)占用了 4,844K 的内存
180K: .ttf mmap ->TrueType 字体文件的内存映射占用了 180K 的内存
0K: Cursor ->游标相关的资源没有占用任何内存
0K: Gfx dev ->图形设备相关的资源也没有占用内存
0K: Other mtrack ->其他内存跟踪资源没有占用内存
- Total PSS by process:同上
- Total PSS by OOM adjustment:同上
- Total PSS by category:同上
- 整体使用情况
Total RAM: 3,697,392K (status normal) ->总共的RAM容量为3697M,这是一台4G手机
Free RAM: 548,930K ( 49,482K cached pss + 448,860K cached kernel + 50,588K free) ->空闲的RAM为 548M(其中包括49M用于缓存 PSS,448M 用于缓存内核,还有 50M是完全空闲的)
DMA-BUF: 119,856K ( 14,080K mapped + 105,776K unmapped) ->表示系统中DMA-BUF的总大小为 119M,它是直接内存访问缓冲区,即不通过cpu将内存映射给用户空间的进程或者硬件设备,其中14M已经映射了,105M还未被映射
DMA-BUF Heaps: 119,808K
DMA-BUF Heaps pool: 75,540K
GPU: 679,348K ( 114,628K dmabuf + 564,720K private) ->GPU占用了679M的内存,其中114M是 DMA-BUF映射而来,564M是GPU独有的
Used RAM: 4,001,150K (2,718,430K used pss + 1,282,720K kernel) ->使用的内存4001M,包括2718M的PSS和1282M的内核内存,这里有个疑问为什么会比总RAM多?
Lost RAM: 182,646K -->丢失的内存
ZRAM: 468,452K physical used for 1,541,632K in swap (2,773,040K total swap)
Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)
疑问1:为什么Used RAM高于Total RAM?
疑问2:DMA-BUF到底是什么?
疑问3:为什么会存在丢失内存?
2)dumpsys meminfo packagename
此命令可以带上包名,查询指定进程的内存详细使用情况,阅读之前先理解《Dirty & Clean & SwapPss》相关概念
C:\Users\Administrator>adb shell dumpsys meminfo io.supercent.pizzaidle
- MEMINFO & App Summary:单位K,反映当前进程两种不同分类的部分占用情况
- Objects & SQL
3)adb shell free
-
Mem total:真实物理内存RAM的总空间,如上是一台4G内存手机的Mem total
-
Mem used:已经使用的物理内存大小,包括一些缓存内存大小
-
Mem free:空闲的物理内存,他和Mem used之和等于Mem total
-
Mem shared:被多个进程共享的内存大小,例如某个共享so可能被多个进程引用
-
Mem buffers:详细参考《swap & buffers & cache》,为了提升类似IO等传输效率,在RAM开辟的一段缓存区域
-
-/+ buffers/cache:其used表示系统实际使用的内存大小(不包含缓存内存大小),主要区别Mem used
-
Swap Total:磁盘上Swap交换空间总容量
-
Swap used:磁盘上Swap交换空间使用的容量,即代表有多少内存数据存储了进来
-
Swap free:磁盘上Swap交换空间未使用的容量。
理解1:Mem total = Mem used + Mem free;可用物理RAM的总大小,可以分为已经使用的Mem used部分,和没有使用的部分。其中Mem used包括实际进程真实使用的,也包括Mem buffers缓存使用的部分。
理解2:Mem total = buffers/cache used + buffers/cache free;可用物理RAM的总大小,可用分为实际使用的buffers/cache used,和空闲的部分。PS:buffers/cache used代表的大小是去除了mem buffers或者cache相关的, 它与Mem used不同真实反映了各个进程真实使用的大小。
理解3:Mem used = buffers/cache used + Mem buffers;Mem used的计算包括了实际使用的和缓存里面的大小。通过Mem used和buffers/cache used的差异可以看出当前缓存空间的使用情况。
理解4:Swap total = Swap used + Swap free;磁盘Swap空间总大小,可以分为已经使用的used部分,和没有使用的部分。它位于磁盘swap,它的大小可以通过配置来指定,往往和已经固定死的RAM没有什么关联,swap used使用率比较高反映当前可用RAM空间不足。
4)adb shell top
这里暂时只针对top命令的内存相关部分进行介绍,如上图,其展示的指标其实和free基本上一致
Mem total = Mem used + Mem free
Swap total = Swap used + Swap free
PS:在同一台机器同一时刻执行top和free命令,他们之间存在一些偏差,但整体来看是差不多的,个人估计可能是内部使用了不同算法来统计或者根本无法做到同一时刻执行,所以建议这点偏差可以忽略。