内存统计口径
整机内存占用
💡 整机内存占用 = 静态预留内存 + 内核占用内存 + 非Cached(oom_adj < 900)进程的Pss总和
静态预留内存 = DDR大小 - memTotal - GCMA
GCMA内存大小获取方式
- 0.执行mount -t debugfs none /sys/kernel/debug;挂载debugfs
- 1.先cd /sys/kernel/mm/cma/;
- 2.遍历目录下每一个子目录<region name>,cat <region name>/gcma,过滤出值为1的region;
- 3.cat /sys/kernel/debug/cma/<region name>/count;
- 4.将所有gcma为1的region的count值累加,最后乘以4,单位为KB)。
内核占用内存 = Kernel(dumpsys meminfo中Used RAM:中的kernel值)- Dma_unmaped(dumpsys meminfo中DMA-BUF:的unmapped值)- GPU_private(dumpsys meminfo中的GPU:的private);它包含kernelCmaUsage,若内核没有使能CONFIG_CMA_FS,会导致dumpsys meminfo统计不到CMA的使用情况,内核内存就计算不准确。
内核占用内存也可以如下公式计算:
内核占用内存 = proc_meminfo.Shmem + proc_meminfo.SUnreclaim + proc_meminfo.VmallocUsed + proc_meminfo.PageTables + proc_meminfo.SecPageTables + proc_meminfo.KernelStack(当CONFIG_VMAP_STACK未使能时;其中iQoo已使能,小米P1已使能) + kernelCmaUsage(dumpsys meminfo中的 Kernel CMA值)
kernelCmaUsage有三种获取方式:
1)dumpsys meminfo中的 Kernel CMA值;
2)cat sys/kernel/mm/cma/<region name>/alloc_pages_success - cat sys/kernel/mm/cma/<region name>/release_pages_success,累加sys/kernel/mm/cma所有子目录,最后*4;
3)cat /sys/kernel/debug/cma/<region name>/used,累加/sys/kernel/debug/cma的所有子目录,最后*4;
进程Pss内存(root版本) = dumpsys_meminfo.TOTAL - dumpsys_meminfo.graphics + Gpu_memory(GL) + DMA_buf。
附件:shell脚本(token: Xd4SbqkQLocnhLxYpyEct0DynFh,下载权限不足,无法获取)
内存基线统计规则
白板流程图(内存基线统计方案思维导图):
整机内存基线
- 方案一
- 已达标部门内存基线
- SR已达标进程内存基线(按OS4.0 实际占用 基线)
- 非图形非DMA内存基线(按OS4.0 实际占用 基线)
- 图形DMA内存基线(按OS4.0 实际占用 基线)
- 未达标部门内存基线
- SR已达标进程内存基线(按OS4.0 实际占用 基线)
- 非图形非DMA内存基线(按OS4.0 实际占用 基线)
- 图形DMA内存基线(按OS4.0 实际占用 基线)
- SR未达标进程内存基线(按OS4.0 目标占用 基线)
- 方案二
- 已达标部门内存基线
- SR已达标进程内存基线(按OS4.0 实际占用 基线)
- 非图形非DMA内存基线(按OS4.0 实际占用 基线)
- 图形DMA内存基线(按OS4.0 实际占用 基线)
- 未达标部门内存基线(按OS4.0 目标占用 基线)
- SR已达标进程内存基线(按OS4.0 实际占用 基线)
- 非图形非DMA内存基线(按OS4.0 实际占用 基线)
- 图形DMA内存基线(按OS4.0 实际占用 基线)
- SR未达标进程暂不内存基线
内存基线分类表
进程内存
| 基线类型 | 内存分类 | Qcom | MTK | XRing | 备注 |
|---|---|---|---|---|---|
| 图形+DMA | GL | UNMAPPED=cat /sys/class/kgsl/kgsl/proc/<pid>/gpumem_unmapped MAPPED=cat /sys/class/kgsl/kgsl/proc/<pid>/gpumem_mapped GL_KB= (UNMAPPED + MAPPED)/1024 | GL_KB=4 * (cat /proc/mtk_mali/gpu_memory 2) | GL_KB=4 * (cat /proc/xgpu/gpu_memory 2) | GPU驱动分配的内存:BufferObject, GLcommand, GLTexture, MemPool, VBO 涉及的进程pid: Qcom: adb shell ls -l /d/kgsl/proc/ MTK: adb shell cat /proc/mtk_mali/gpu_memory XRing: adb shell cat /proc/xgpu/gpu_memory |
| 图形+DMA | DMA(含EGL) | dmabuf_dump | dmabuf_dump | dmabuf_dump | 通过gralloc等分配dmabuf内存:图形、多媒体、相机。 |
| 图形+DMA | Native堆图形内存 | GPU驱动 libGLESv2_adreno, vulkan.adreno, libadreno_, libgsl, libCB, libRCC, libllvm-qgl, libllvm-glnext Display HAL mapper.qti, libgrallocutilsng, libgralloc.qti, libgralloc.system.qti, libgralloccore, vendor.qti.hardware.display.snapalloc-impl, libsdmcore, libsdmextension, libqservice, eglSubDriverAndroid | GPU驱动 libGLES_mali, vulkan.mali, libmtk_mali Graphics mapper.mediatek, libgralloc_extra, libmtk_drvb, libmtk_colortm | libGLES_mali, vulkan.mali mapper.xring, vendor.xring.hardware.display.composerext, vendor.xring.hardware.gamingplus | GPU驱动动态库和显示框架动态库分配的native内存 Graphics Framework: libhwui, libgui, libEGL, libGLESv2, libvulkan, libui, libskia, libnativewindow HAL/AIDL: android.hardware.graphics.allocator-V2-ndk, android.hardware.graphics.composer3 小米显示特性(XRing): vendor.xiaomi.hardware.display.mihwcextension, vendor.xiaomi.hardware.displayfeature_aidl, vendor.xiaomi.hardware.pqservice |
| 非图形非DMA | 1、showmap <pid> 2、从showmap结果中提取/dev/kgsl-*的Pss内存作为GfxDev 3、Pss + SwapPss - Native堆图形内存 - GfxDev | 1、showmap <pid> 2、Pss + SwapPss - Native堆图形内存 | 1、showmap <pid> 2、Pss + SwapPss - Native堆图形内存 | 包括代码、数据、文件、线程栈、java堆、native堆及其他内存;但排除native堆图形内存和GfxDev内存 |
内核/静态/LostRAM(字段定义中,具体数值待填充)
| 进程/子系统 | 基线类型 |
|---|---|
| 内核 | 内核占用 |
| 内核 | 驱动占用 |
| 内核 | 进程占用 |
| 静态预留 | HLOS |
| 静态预留 | 器件 |
| LostRAM | - |
Dumpsys meminfo
| Framework | 计算方式 | 详情 | 备注 |
|---|---|---|---|
| Total RAM | =meminfo.MemTotal | ||
| Free RAM | =cachedPss + MoreCachedSize(原生CachedSize) + meminfo.Free | cachedPss = ADJ>=900的所有进程Pss之和 MoreCachedSize = meminfo.KReclaimable + meminfo.Buffers + meminfo.Cached CachedSize = MoreCachedSize - meminfo.Mapped | 小米:重复统计了Adj >= 900进程的meminfo.Mapped; Google: 未包含被进程 |
| Used RAM | = totalPss - cachedPss + kernelUsed | totalPss = 所有进程Pss之和 - memtrack_graphics + dmabufMapped - memtrack_gls(当gpuUsage和gpuPrivateUsage都大于等于0时) kernelUsed = meminfo.Shmem + meminfo.SUnreclaim + meminfo.VmallocUsed + meminfo.PageTables + meminfo.KernelStack(当CONFIG_VMAP_STACK未使能时) + ionUnmapped(当ionHeap和ionPool都大于等于0时;ionUnmapped = ionHeap - dmabufMapped)或dmabufUnmapped(dmabufUnmapped = totalExportedDmabuf - dmabufMapped)+ gpuPrivateUsage(当gpuUsage和gpuPrivateUsage都大于等于0时)+ kernelCmaUsage | 华为mate60 pro(鸿蒙4.2对应android S): totalPss = 所有进程Pss之和(Pss仅包括GL内存) kernelUsed = meminfo.Shmem + meminfo.SUnreclaim + meminfo.VmallocUsed + meminfo.PageTables + meminfo.KernelStack + gpuPrivateUsage(当gpuUsage大于0时) 其他友商竞品与小米一致 |
| Lost RAM |
ionHeap
ionPool
totalExportedDmabuf
dmabufMapped
gpuUsage
gpuPrivateUsage
kernelCmaUsage
应用的gpu内存和dma内存
💡 Dumpsys meminfo中应用GLmtrack和EGLmtrack都是Memtrack通过各芯片厂商实现的Hal从内核节点中获取的;
GLmtrack
1)Qcom:仅统计了进程 unmapped的gpumem(cat sys/class/kgsl/kgsl/proc/5796/gpumem_unmapped,393216Bytes = 384KB,对应dumpsys meminfo截图中GLmtrack)
2)MTK:统计kctx的used_pages(cat /proc/mtk_mali/gpu_memory | grep <pid>)
3)Xring:统计kctx的used_pages(cat /proc/xgpu/gpu_memory | grep <pid>)
EGLmtrack
1)Qcom:统计进程分配的ion内存(cat /d/kgsl/proc/5796/mem | grep ion)
2)MTK:统计进程正使用的按比例分摊的dma内存(echo “pid: <pid>” > proc/dma_heap/rss_pid, cat proc/dma_heap/rss_pid, 取userspace_pss)
3)Xring:统计进程(待补充)
dmabuf
dmabuf_dump命令导出的结果中按pid匹配找到进程的dmabuf信息块,对比EGLmtrack(例如:高通平台 cat /d/kgsl/proc/5796/mem | grep ion),可以看到完全被dmabuf包含(按Inode匹配)
💡 为了准确评估应用业务的内存占用,需要将gpu内存和dmabuf内存按showmap的Pss内存分摊方式,归属给具体业务进程,请芯片厂商考虑修改memtrack统计方式,或评估是否认可如下计算方式(先剔除memtrace返回的GL和EGL,然后通过从kgsl内核节点和dmabuf_dump命令获取gpu和dmabuf的Pss值):
进程Pss内存 = PSS(dumpsys) + SwapPss(dumpsys) - Graphic(dumpsys) + unmapped_gpumem(cat sys/class/kgsl/kgsl/proc/5796/gpumem_unmapped) + mapped_gpumem(cat sys/class/kgsl/kgsl/proc/5796/gpumem_mapped) + dmabuf_pss(dmabuf_dump结果中匹配进程pid)