dumpsys meminfo 的原理和应用

2023-11-16

什么是dumpsys meminfo

Android中通过命令dumpsys meminfo package_name|pid, 查看指定进程的内存使用情况.通过输出的信息,可以看出来应用在内存哪里分配出现了问题,比如native heap 分配高,就要查一下自己的native部分的代码哪里分配后没有及时释放。

这条命令是如何工作的?

Android中的Service都会注册到ServiceManager,每个Service要实现binder定义的接口,其中的dump方法dump(int fd, const Vector<String16>& args),通过给定的参数,把信息送到文件描述符fd中。

dumpsys位于/system/bin/dumpsys.运行时它首先后获得ServiceManager,然后根据参数查找服务,找到后,然后binder调用服务的dump方法.而meminfo是系统的一个服务(内部则是一个MemBinder的类实现的),当dumpsys找到这个服务后,调用dump方法,通过传递的参数,显示出进程内存使用情况。

 下面是一个进程的meminfo。

上面图中的数据分A和B两个部分, A 部分是进程内存的详细信息, B 部分是对详细信息进行的总结。

而A部分的数据是从哪里读到的?

通过以下三个方式,图中A.1部分的信息是通过解析/proc/pid/smaps获得的, A.2 通过IPC (binder 和pipe)方式获得。而A.3通过memtrack.vendor_xxx.so中的接口获得的。

下面将从A, B 两个部分,详细介绍这些数值是如何生成的。

A部分

A.1 smaps

下面是meminfo读取进程的smaps从上到下的调用关系图。

读取进程smaps的节点

根据属性的不同,进程的虚拟地址空间被划分成若干个vma,每一个vma通过vm_next和vm_prev组成双向链表,链表头位于进程的task->mm->mmap.当通过proc接口读取进程的smaps文件时,内核会首先找到该进程的vma链表头,遍历链表中的每一个vma, 通过walk_page_vma统计这块vma的使用情况,最后显示出来。

下图是一块vma的统计信息

解析smaps用到了以下几个字段.

  • Pss
    PSS (Proportional Set Size) = 进程独占的内存 + 进程程共享的内存 / 映射次数。
    内存的管理是以 page 为单位的, 如果 page 的 _refcount或者 _mapcount为 1, 那么就是进程独占的内存. 也叫 private. 如果 page 的 _mapcount 为 n ( n >= 2), 这块内存以 page / n 来统计。

     

  • Private_Dirty
    Private 在上面已经说过了。 而 Dirty 分为 PageDirty和 pte_dirty. PageDirty就是所说的脏页( 文件读到内存中被修改过, 就会标记为脏页)。 pte_dirty则当 vma 用于 anonymous 的时候, 读写这段 vma 时候, 触发 page fault, 调用 do_anonymous_page , 如果vma_flags中包含 VM_WRITE, 则会通过 pte_mkdirty(entry)标记。

     

  • Private_Clean
    与 Private_Dirty 相反。

     

  • Swap
    一般情况下, 在 Android 中就是 zram, 通过压缩内存页面并将其放入动态分配的内存交换区来增加系统中的可用内存量, 压缩的都是匿名页。

但下面这段vma是文件映射的,但还有swap字段的,这是因为这个文件是通过mmap到进程地址空间的。当标记中有MAP_PRIVATE时,这表示是一个copy-on-write的映射,虽然是file-backed , 但当向这个数据写入数据的时候,会把数据拷贝到匿名页里,所以看到上面的Anonymous:也不为0。

A.1信息的分类则通过vma的名字进行字符串匹配,然后将内存信息划分为不同的部分

1. vma用于file时


当vma->vm_file不为空的时候,名字为file->f_path文件路径,文件包含存储介质的文件,也包含设备文件,虚拟文件等(everything is a file)。

下面是meminfo的字段对照表

类型

匹配字符串

Ashmem

/dev/ashmem

Gfx dev

/dev/kgsl-3d0

Other dev

/dev/*

.so mmap

*.so 例 /system/lib64/libstdc++.so

.jar mmap

*.jar 例 /system/framework/framework.jar

.apk mmap

*.apk 例 /system/framework/framework-res.apk

.ttf mmap

*.ttf 例 /system/fonts/Roboto-BlackItalic.ttf

.dex mmap

*.vdex 例 /system/framework/boot.vdex

.oat mmap

*.oat 例 /system/framework/arm64/boot-ext.oat

.art mmap

*.art 例 /system/framework/arm64/boot.art

Other mmap

不属于上面的类型

例如在解析vma过程中,如果vma的名字包含/dev/kgsl-3d0的时,就把它归在Gfx Dev 这类。

 

2. vma 用于anonymous时


这种用途的vma的名字[anon:开头,虽然叫匿名,但显示哪里分配的,比如说上图的[anon:libc_malloc],就说明这段vma是从libc_malloc中分配出去的。
老的内核版本是没有这个域的,后来因为userspace的进程有很多种不同的分配器(allocators) , 如果出现异常不知道哪里出了问题,就比如说如何区分Dalvik Heap 和Native Heap, 后来android提了一笔可以修改内存区域的名字的补丁,通过prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, (unsigned long)name)系统调用,就可以把名字保存在vma_area_struct ->shared.anon_name有趣的这是个userspace指针,来降低mm子系统的复杂性.同时复用了vma_area_struct结构体的shared(利用union),shared用在file-backed mappings,这样就不和用于匿名的vma冲突.连内存都省了(这可能就是程序的魅力所在)。

下面是meminfo的字段对照表

类型

匹配字符串

Native Heap

[anon:libc_malloc] 或 [heap]

Dalvik Heap

[anon:dalvik-*

Dalvik Other

Dalvik Heap 的部分 比如 [anon:dalvik-indirect ref 开头的)

 

A.2进程中读取

下面是从meminfo读取进程运行状态的信息调用图.这部分信息是通过IPC方式获得。

Meminfo打开一个pipe,通过异步binder调用并传递了pipe fd, 然后开始监听fd,应用进程获得了这个pipe fd后 读取需要的内存数据,通过pipe传递到AMS中。

  • mallinfo()
    返回内存分配的统计信息, 函数声明在 android/bionic/libc/include/malloc.h,函数定义在 android/bionic/libc/bionic/malloc_common.h.

     

#if defined(USE_SCUDO)

#include "scudo.h"
#define Malloc(function) scudo_ ## function

#else

#include "jemalloc.h"
#define Malloc(function) je_ ## function

#endif

函数调用Malloc(mallinfo),这是对mallinfo进行封装,来加载不同的分配器对应函数的实现.因为Android使用的是jemalloc,也就会调用je_mallinfo()。

malloc结构体定义,返回struct mallinfo。

下面是meminfo和mallinfo字段对照表

Native Heap Size

mallinfo.usmblks

Maximum total allocated space

Native Heap Alloc

mallinfo.uordblks

Total allocated space

Native Heap Free

mallinfo.fordblks

Total free space

  • runtime

     

Runtime runtime = Runtime.getRuntime();

// Do GC since countInstancesOfClass counts unreachable objects.
runtime.gc();

long dalvikMax = runtime.totalMemory() / 1024;
long dalvikFree = runtime.freeMemory() / 1024;
long dalvikAllocated = dalvikMax - dalvikFree;

 

通过上面获得Java虚拟机的内存使用情况

下面是meminfo和runtime的字段对照表

Dalvik Heap Free

runtime.freeMemory()

Dalvik Heap Size

runtime.totalMemory()

Dalvik Heap Alloc

Dalvik Heap Size - Dalvik Heap Free

A.3 memtrack.vendor_xxx.so

下面是meminfo读取进程在GPU上分配内存的从上到下调用关系图。

读取进程在GPU上分配的内存

每个厂商统计的策略可能不一样,这也是出现HAL层的原因. 下面以高通SDM710为例。从代码中可以看到也是读内核中GPU文件节点,然后解析数据的。

 

B部分 

  • Java Heap

     

// dalvik private_dirty
 dalvikPrivateDirty
// art mmap private_dirty + private_clean  
+ getOtherPrivate(OTHER_ART);

dalvik private dirty包含任何写过zygote分配的页面(应用是从zygote fork 出来的),和应用本身分配的。

art mmap是应用的bootimage,任何private页面也算在应用上。

 

  • Native Heap

     

nativePrivateDirty; // libc_malloc

通过libc_malloc库分配的大小

 

  • Code

     

// so mmap private_dirty + private_clean  
 getOtherPrivate(OTHER_SO)  
// jar mmap private_dirty + private_clean    
+ getOtherPrivate(OTHER_JAR)
// apk mmap private_dirty + private_clean      
+ getOtherPrivate(OTHER_APK)
// ttf mmap private_dirty + private_clean      
+ getOtherPrivate(OTHER_TTF)
// dex mmap private_dirty + private_clean      
+ getOtherPrivate(OTHER_DEX)
// oat mmap private_dirty + private_clean
+ getOtherPrivate(OTHER_OAT);

所有私有静态资源求和。

 

  • Stack

     

// stack private_dirty
getOtherPrivateDirty(OTHER_STACK);

进程本身栈占用的大小。

 

  • Graphic

     

//Gfx Dev private_dirty + private_clean
getOtherPrivate(OTHER_GL_DEV)
// EGL mtrack private_dirty + private_clean      
+ getOtherPrivate(OTHER_GRAPHICS)
// GL mtrack private_dirty + private_clean      
+ getOtherPrivate(OTHER_GL);

进程在GPU上分配的内存。

 

  • System

     

Pss Total 的和- Private Dirty 和Private Clean 的和

系统占用的内存,例如一些共享的字体,图像资源等。

 

应用

当我们查看应用的内存消耗情况时,可以通过meminfo提供的信息,判断应用中哪个模块使用的内存出现问题。

下面是同一个应用A和B版本的meminfo:

A版本

B版本

对比A B 版本,先看App Summary, 可以明显发现Graphic占用高,而Graphic是由Gfx, EGL 和GL组成,从两图对比看主要是EGL部分, EGL 是进程在GPU上分配的内存,查看平台对应的GPU内存调试的接口

通过对比发现B版本EGL部分主要是发生在使用egl_image上,查看代码发现egl_image是从hardware bitmap 分配的,这是Android O 上的一个bitmap的新特性。B 版本使用后,没有及时释放所致。

参考文献:

[1]https://developer.android.com/studio/command-line/dumpsys

[2]http://man7.org/linux/man-pages/man5/proc.5.html

[3]https://bumptech.github.io/glide/doc/hardwarebitmaps.html

扫码关注
“内核工匠”微信公众号
Linux 内核黑科技 | 技术文章 | 精选教程
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

dumpsys meminfo 的原理和应用 的相关文章

  • cpuz测试分数天梯图_2015最新cpu天梯图 cpu性能排行榜

    西安兵马俑在线3月19日讯查找排名方法 搜索CPU型号 例如 按Ctrl F键 搜 i7 5960X 这个CPU型号 若需获知个人使用的电脑CPU具体型号 查看计算机属性 或用CPU Z这个软件 常用名词解释 CPUModel 处理器型号
  • vsCode关闭代码检查工具

    在script标签里 第一行输入下面的内容即可 转载于 https www cnblogs com caoxueying2018 p 10062329 html
  • 内核运行环境

    复杂度2 5 机密度2 5 最后更新2021 05 06 AIX内核有两种运行环境 process environment和interrupt environment 用户进程call内核系统调用 或者内核系统调用嵌套call其它系统调用
  • 2023年信息与通信工程国际会议(JCICE 2023)

    会议简介 Brief Introduction 2023年第二届信息与通信工程国际会议 JCICE 2023 会议时间 2023年5月12日 14日 召开地点 中国 成都 大会官网 JCICE 2023 2023 International
  • DeeplabCut安装教程(CPU)版

    DeeplabCut安装教程 CPU 版 文章目录 DeeplabCut安装教程 CPU 版 前言 安装步骤 1 进入官网下载对应的DeepLabCut zip文件 附官网链接 2 解压到任意位置 3 打开Anaconda Navigato
  • c++模板(函数模板,类中函数模板,类模板)

    作用 减少程序中的冗余信息 如 多个函数或类的除了参数类型外 其余都完全相同时 可以使用模板来减少重复信息 参考函数重载时 输入参数数量也相同的情况 1 函数模板 即建立一个通用函数 只不过该函数的返回类型和形参类型都不具体指定 其定义格式
  • Python实现找零兑换的三种解法

    找零兑换 找零兑换问题最直接的解法就是贪心策略 比如问题 有面值1 5 10 25的硬币 求解兑换63元所需的最少硬币数 贪心策略的思想就是不断的利用面值最大的硬币去尝试 不行了 在尝试较小面值的硬币 该例中也即使用25的硬币去尝试 2枚2
  • 华为服务器怎么换系统,云服务器怎么更换系统

    云服务器怎么更换系统 内容精选 换一换 弹性云服务器系统密码涉及到客户重要的私人信息 提醒您妥善保管密码 如果您忘记密码或密码过期 可以重置密码 如果弹性云服务器提前安装了密码重置插件 请参见在控制台重置弹性云服务器密码 使用公共镜像的弹性
  • 【简单易用】基于Qt的跨平台自定义标题栏控件QJamWindow

    一 概述 QJamWindow是一个基于Qt的跨平台自定义标题栏控件 你可以通过它方便得设计出属于自己的标题栏 特性 1 标题栏高度可调 标题栏背景色设定 2 图标及其尺寸 图标背景色设定 3 Control box宽度 鼠标经过 按下颜色
  • JAVA基础必备功能之导出ZIP文件

    导出ZIP文件 比较常用的两种 导出图片压缩文件 导出excel压缩文件 导出思路 需要导出的文件转存为byte数组保存到Map 然后遍历压缩成zip 需要引入jar
  • 链表— —循环链表的算法实现

    Joseph问题 有 10 个小朋友按编号顺序 1 2 10 顺时针方向围成一圈 从 1 号开始顺时针方向 1 2 9 报数 凡报数 9 者出列 显然 第一个出圈为编号 9 者 最后一个出圈者的编号是多少 第 5 个出圈者的编号是多少 in
  • lintcode 631 · 最大矩阵II【矩阵 中等 vip】

    题目 https www lintcode com problem 631 给出一个只有 0 和 1 组成的二维矩阵 找出最大的一个子矩阵 使得这个子矩阵的主对角线元素均为 1 其他元素均为 0 你可以认为所求的矩阵一定是一个方阵 主对角线
  • 组是由圆括号分开的正则表达式 随后可以根据它们的组号进行调用 第 0 组表示整个匹 配表达式 第1 组表示第 1 个用圆括号括起来的组 等等 因此 在表达式 A B C D 中 有 3 个组 第 0 组 ABCD 第 1 组是 BC 以及第
  • Acwing790.数的三次方根

    解题思路 include
  • Pandora-ChatGPT(离线安装教程)(附安装包)

    要安装Pandora ChatGPT 1 1 0 tar gz 您可以按照以下步骤进行操作 安装包 https wwue lanzouj com iOMwG0yeozxg 解压缩文件 tar xvf Pandora ChatGPT 1 1
  • 设置bitmap的宽高,同时将bitmap转换为file对象

    public class BitmapToSizeChangeFile 将bitmap转换为file存储起来 param bitmap return public static File
  • Dijkstra C艹板子

    迪杰斯特拉算法主要特点是从起始点开始 采用贪心算法的策略 每次遍历到始点距离最近且未访问过的顶点的邻接节点 直到扩展到终点为止 题源 最短路 蓝桥云课 lanqiao cn 如下图所示 G 是一个无向图 其中蓝色边的长度是 1 橘色边的长度
  • 绕过JavaScript debugger三种解决方法

    最近网上挺火的一段加密混淆JS 格式化展开后有300多行 目的是解析生成一个cookie 不携带cookie 就不能加载网页源码 典型的反爬虫操作 看后觉得好使的请记得点赞哦 烧鸡么么哒 谢谢 JS会自动监视是否打开了调试器 如果打开了 就
  • STM32锁住,解开方法

    一 STM32 被锁住后的解开方法 问题 STM32 JTAG SWD禁用导致无法烧写 由于STM32的引脚功能较多 在为了方便硬件的使用 常会使用复用重映射的功能 这里主要涉及的是SWD和JTAG端口的引脚对应出现的问题 为了使得TIM2
  • php之RSA加密解密

    介绍 RSA算法属于非对称加密算法 非对称加密算法需要两个秘钥 公开密钥 publickey 和私有秘钥 privatekey 公开密钥和私有秘钥是一对 如果公开密钥对数据进行加密 只有用对应的私有秘钥才能解密 如果私有秘钥对数据进行加密那

随机推荐

  • Linux下nginx的安装以及环境配置

    linux下nginx的安装以及环境配置 刚好最近在处理服务器相关的工作 所以记录一下nginx的安装 ok 接下来直接开始操作 第一步 下载nginx压缩包 在这里可以去nginx官网下载 gt 点我下载nginx 也可以直接使用wget
  • 【解惑】一文告诉你,该学R还是Python!

    Python和R是统计学中两种最流行的的编程语言 R的功能性主要是统计学家在开发时考虑的 R具有强大的可视化功能 而Python因为易于理解的语法被大家所接受 在这篇文章中 我们将重点介绍R和Python以及它们在数据科学和统计上地位之间的
  • 提高 React 项目整洁度的 21 个最佳实践

    React 在如何组织结构方面非常开放 这正是为什么我们有责任保持项目的整洁和可维护性 今天 我们将讨论一些改善 React 应用程序健康状况的最佳实践 这些规则被广泛接受 因此 掌握这些知识至关重要 所有内容都将以代码展示 所以做好准备
  • 端口扫描技术

    端口扫描 常见的扫描类型 全连接扫描 TCP connect 扫描 半连接扫描 TCP SYN 扫描 IP 头信息 dumb 扫描 秘密扫描 TCP FIN 扫描 TCP ACK 扫描 NULL 扫描 XMAS 扫描 SYN ACK 扫描
  • SQL编程:存储过程、触发器、函数(实例基于MySQL5.7.12)

    SQL编程基础 A 编程环境 即存储过程 触发器和函数中进行SQL编程 所以有些语法并不能应用于普通的SQL应用场景 如命令行直接SQL查询 B 变量声明 1 全局变量 声明 set 变量名 值 读取 select 变量名 赋值 set 变
  • 联想gen系列服务器,Hpe Microserver Gen10 Plus开箱

    Hpe Microserver Gen10 Plus开箱 2021 04 19 10 53 23 25点赞 69收藏 83评论 心水很久的gen10 plus终于到了 关注了很久终于下手了 在值得买好像都没看到gen10 plus的开箱 那
  • vuex的持久化插件

    目的 让在vuex中管理的状态数据同时存储在本地 可免去自己存储的环节 在开发的过程中 像用户信息 名字 头像 token 需要vuex中存储且需要本地存储 再例如 购物车如果需要未登录状态下也支持 如果管理在vuex中页需要存储在本地 1
  • 参考《一个64位操作系统的设计与实现》,自己写操作系统(一)

    1 安装VMware虚拟机 版本16 下载地址 http downdownxia com down VMware16lsb rar key fa4505a42b82aa65195be879fc84defd 2 安装centos系统 版本6
  • 【项目实战】MySQL查询计算某个字符在某个字段中的数量

    一 背景说明 表sys dept中有个字段 ancestors ancestors的值是含有 逗号 现在需要计算 逗号 这个字符串在ancestors中出现的数量 二 解决方案 SELECT dept id dept name ancest
  • 2023华为od机试 Python【最长公共后缀】

    题目 我们现在要实现一个功能找到字符串数组 中的最长公共后缀如果不存在公共后缀 输入描述 abc bbc c 输出描述 c 示例1 输入 abc bbc c 输出 c 说明 返回公共后缀 c 示例2 输入 aa bb cc 输出 Zero
  • 解决微信小程序报错:[渲染层网络层错误] Failed to load local image resource

    一 场景 写了一个图片点击 全屏展示的组件 页面图片 gt 点击 gt 打开全屏遮罩层显示大图片 1控制元素展示的变量 data photoShow false 2图片点击函数 onClick const url null e curren
  • Shell的read 读取控制台输入、read的使用

    文章目录 1 read 读取控制台输入 1 1基本语法 1 2read的使用 如果想看更详细的Shell总结请到我之前写的博客https blog csdn net Redamancy06 article details 126048299
  • com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 2 of 2-byte

    com sun org apache xerces internal impl io MalformedByteSequenceException Invalid byte 2 of 2 byte UTF 8 sequence 分析 这个问
  • YOLO-----关于正负样本、Loss、IOU、怎样去平衡正负样本的问题?

    关于正负样本 Loss IOU 怎样去平衡正负样本的问题 1 关于正负样本 2 Loss计算 3 IOU GIOU DIOU CIOU 4 怎样去平衡正负样本的问题 先整理一下anchor的概念 常用的anchor定义 Faster R C
  • MySQL 8 安装教程

    MySQL 8发布了 据说相比MySQL 5速度提升了2倍 今天来搞一搞MySQL 8 一 下载MySQL 8 1 首先当然是下载安装包了 下载地址 点击下载MySQL 8 这个页面相信大家都熟悉 我就不多说了 2 将下载的压缩包解压 解压
  • 全网最简洁的mpy-cross教程

    大家知道我一向精干 不喜欢搞花儿的 如果去mpy官网看mpy cross的相关资料 估计又得绕蒙 跟我来 保证你三分钟学会 但是本文不涉及原理 第一 mpy cross是干嘛滴 答 把py文件转成mpy系统读的mpy文件 术语咱不懂 叫交叉
  • H3C交换机如何配置SNMP协议?

    1 使用telnet 登陆设备 system view snmp agent snmp agent community read public snmp agent sys infoversion all dis cur save 保存 Y
  • 操作系统原理大题

    一 地址变换和求FAT表大小 某一页表内容自0 7依次为03 07 0B 11 1A 1D 20 22 请计算页面大小为1K和4K时的逻辑地址134D对应的物理地址 首先 将134D转换为二进制数为 0001001101001101 1k为
  • 【2024届校招内推:NTAA84y】腾讯云智研发中心

    云智校招新官网查看最新岗位情况 云智研发中心2024届校园招聘官网 内推码 NTAA84y 云智研发公司2024届校园招聘启动啦 腾讯旗下子公司 八大类岗位 五大城市全面开放 在喜欢的城市 做喜欢的工作 期待正能量 共担当 实干家的你加入云
  • dumpsys meminfo 的原理和应用

    什么是dumpsys meminfo Android中通过命令dumpsys meminfo package name pid 查看指定进程的内存使用情况 通过输出的信息 可以看出来应用在内存哪里分配出现了问题 比如native heap