dumpsys 详解:cpuinfo、meminfo、battery、procstats、graphics
dumpsys 是 Android 调试桥(ADB)里的一个“瑞士军刀”。说白了,它能帮你拉出系统服务几乎所有的状态数据。我平时做性能分析,第一个想到的就是它。
但很多人只用 dumpsys meminfo 查个内存,太可惜了。今天我把五个常用子命令逐个拆开讲,包括怎么看输出、关键指标在哪里,以及我踩过哪些坑。
dumpsys cpuinfo – 抓 CPU 的瞬时“心电图”
命令很简单:adb shell dumpsys cpuinfo。输出长这样:
Load: 1.45 / 1.12 / 0.89
CPU usage from 0ms to 3000ms:
40% com.example.app: 30% user + 10% kernel / faults: 12 minor
20% system_server: 15% user + 5% kernel / faults: 3 minor
15% surfaceflinger: 12% user + 3% kernel
...
关键指标只有三个:Load(系统负载)、进程 CPU 占比、user/kernel 拆分。Load 的 3 个值分别是 1/5/15 分钟平均负载,数值接近 CPU 核数说明快满了。
我曾经遇到一个诡异的卡顿问题:CPU 总占用不高,但动画掉帧严重。后来发现是 kernel 部分占比异常高(超过 30%),说明内核态在反复做 I/O 或锁竞争。一查确实是某个驱动有 bug。
dumpsys cpuinfo,配合 top -n 1 -d 1 交叉验证。因为 dumpsys 默认只显示最近的 3 秒数据,拿到的是“快照”,多个快照才能看出趋势。
dumpsys meminfo – 别只看 PSS,还有更多隐藏信息
最常用的内存排查命令。但不只是 adb shell dumpsys meminfo 包名 那么简单。
完整命令:
adb shell dumpsys meminfo com.example.app -d # 显示 Dalvik 堆细节
adb shell dumpsys meminfo -a # 所有进程汇总
输出中我重点看这几项:
- PSS Total – 物理内存的真实占用,单位 kB。它已经按比例分摊了共享库,最接近实际消耗。
- Heap Alloc / Heap Free – Java 堆的分配和空闲。如果 Heap Alloc 接近 Heap Size,说明堆快撑爆了。
- Views / Activities – 如果 Activity 销毁后这里还不降,那就有内存泄漏的味道了。
- Native Heap – C/C++ 分配的内存,很多图片或音视频操作会在这里暴增。
我有个亲身教训:某读图应用内存一直涨,PSS 到 800MB 还没崩。查 native heap 发现一个图片解码库没及时释放 buffer,改了一行代码直接降到 200MB。所以别只盯着 Java heap。
dumpsys battery – 电池数据是个宝
命令:adb shell dumpsys battery。输出:
Current Battery Service state:
AC powered: false
USB powered: true
level: 85
scale: 100
voltage: 3875
temperature: 295
technology: Li-ion
screen on: true
电池数据看似简单,但有两个场景特别好用:
- 功耗基准测试前重置:用
dumpsys battery unplug模拟断开充电器,再dumpsys battery reset重置统计,然后跑场景,最后看level的变化量。我习惯用这个做短时间的功耗对比。 - 定位唤醒锁问题:配合
dumpsys power查看 wake lock 的持有进程。某次我查到一个第三方 SDK 持有一个长时间 PARTIAL_WAKE_LOCK,导致一夜掉电 30%。
dumpsys battery set level 50 这种设置只在测试机上有效,真实设备可能会有保护机制。另外测试完后一定要 dumpsys battery reset 恢复正常状态,不然 battery stats 会一直不准。
dumpsys procstats – 内存历史的“时间胶囊”
这个命令能告诉你过去几小时或几天里,每个进程在不同内存状态下的运行时长。语法:
adb shell dumpsys procstats --hours 24 # 最近24小时
adb shell dumpsys procstats com.example.app --hours 6
输出是一张表格,类似:
| 进程 | 状态 | PSS 区间 (KB) | 持续时间 |
|---|---|---|---|
| com.example.app | Foreground | 200K-300K | 2h 15m |
| com.example.app | Background | 100K-150K | 1h 30m |
| system_server | Foreground | 400K-500K | 3h 0m |
我最喜欢用它做 内存蓄水池分析。如果你的应用后台待机时 PSS 持续增长,说明有内存泄漏的趋势。你想想看,线上用户的所有行为你不可能都重现,但 procstats 就像黑匣子,记录了真实的运行轨迹。
dumpsys meminfo。procstats 指方向(哪个进程在后台偷偷占内存),meminfo 去定位(具体是什么对象泄露)。
dumpsys graphics – 渲染性能的“照妖镜”
命令:adb shell dumpsys graphics com.example.app。输出焦点:
Stats since: 1234567890ms
Total frames rendered: 1500
Janky frames: 45 (3.00%)
Frame time percentiles:
50th: 8ms
90th: 14ms
95th: 18ms
99th: 28ms
Number of frames with:
...
Overrun: 12
核心理念是看 掉帧率(Janky frames) 和 帧时间分布。16ms 内完成为流畅,超过 16ms 算掉帧。90th 百分位和 99th 百分位很关键——如果你 99th 到了 30ms,那就说明偶发卡顿会频繁出现。
我项目里一次线上用户反馈“滑动列表偶尔卡”,本地完全复现不了。靠 dumpsys graphics 抓到了某页面 99th 帧时间 40ms,再配合 systrace 发现是 View 的 onDraw 里做了一次磁盘读取。
adb shell setprop debug.hwui.profile true 才能输出更详细的帧数据。另外,要清空旧数据再跑场景:dumpsys graphics com.example.app reset。
速查对比表
| 子命令 | 核心数据 | 常用场景 | 我的经验 |
|---|---|---|---|
| cpuinfo | Load, 进程CPU% | 瞬时CPU高负载定位 | 结合kernel占比查驱动问题 |
| meminfo | PSS, Heap, Native | 内存泄漏、峰值确认 | 别忘看Native Heap |
| battery | level, status | 功耗对比、唤醒源定位 | 先unplug再测试 |
| procstats | PSS区间 + 时长 | 后台内存行为监控 | 长期自动化采集很好用 |
| graphics | Janky%, 帧时间百分位 | 渲染性能量化、线上卡顿复现 | 配合systrace更准 |
以上几个命令,熟练了能解决大部分 Android 性能的“表面问题”。我个人习惯把它们写成一套自动化脚本,每天睡前跑一轮,第二天上班直接看结果。嗯,比手动敲命令省心多了。