Android Perfetto 系列 14:heapprofd 与内存 Profiling
dumpsys meminfo 显示GF程内存上涨,Java heap dump 却没有对应的对象上升时,下一步先查上涨落在 Native Heap、图形 Buffer,还是其他映射。若可疑部分来自 malloc/new,heapprofd 可以把分配与调用栈对应起来。
heapprofd 的分配、释放和调用栈记录能与业务事件放在同一topics Perfetto 时刻轴上,便于核对一次操作前后哪些分配仍未释放。
heapprofd 是采样工具,看到的 native allocation 不能直接当作 RSS,也不覆盖 Java 对象引用或所有图形 backing 内存。先分清内存账,再决定是否抓 profile。我更倾向先用 meminfo 和 smaps 把上涨Source拆开,再打开 flamegraph; 若涨的是 GraphicBuffer,盯着 malloc 调用栈改代码就找错了方向。
Perfetto 系列文章
- Android Perfetto 系列目录
- Android Perfetto 系列 1:Perfetto 工具Description
- Android Perfetto 系列 2:Perfetto Trace 抓取
- Android Perfetto 系列 3:熟悉 Perfetto View
- Android Perfetto 系列 4:使用命令行在本地打开超大 Trace
- Android Perfetto 系列 5:Android App 基于 Choreographer 的渲染流程
- Android Perfetto 系列 6:为什么是 120Hz?高刷新率的优势与挑战
- Android Perfetto 系列 7:MainThread 和 RenderThread 解读
- Android Perfetto 系列 8:深入理解 Vsync 机制与表现分析
- Android Perfetto 系列 9:CPU 信息解读
- Android Perfetto 系列 10:Binder 调度与锁比拼
- Android Perfetto 系列 11:PerfettoSQL、Trace Processor 与回归检测
- Android Perfetto 系列 12:Trace 数字流与丢GA排查
- Android Perfetto 系列 13:Perfetto SDK、Track Event 与 App 现场 Trace
- Android Perfetto 系列 14:heapprofd 与内存 Profiling
- Android Perfetto 系列 15:Boot Trace、长时段现场 Trace 与偶发难题抓取
- Android Perfetto 系列 16:GPU、Power Counters 与硬件瓶颈分析
- Android Perfetto 系列 17:专项场景自动化、难题清单与Draw台体系
- Android Perfetto 系列 18:响应速度实战,从输入事件到首帧反馈
- Video(B站) - Android Perfetto 基础和案例分享
- 影像(B站) - Android Perfetto 分享 - 出图类型分享:AOSP、WebView、Flutter + OEM 系统优化分享
内存问题要分几张账
开始抓 heapprofd 前,先把内存统计结果分成几类。很多误判都来自把它们混在一起。
| 数据 | 常见Source | 回答什么问题 |
|---|---|---|
| GF程 RSS / swap 趋势 | linux.process_stats | 目标GF程 RSS、anon/file RSS、swap、oom_score_adj 有没有变化 |
| GF程 PSS / Private Dirty | dumpsys meminfo、/proc//smaps_rollup、process_stats_config.scan_smaps_rollup | PSS、Private Dirty、SwapPss 是否上涨; scan_smaps_rollup 受Scopes和目的GF程限制 |
| 系统内存压力 | linux.sys_stats | MemAvailable、Cached、ZRAM、vmstat、PSI 是否Description系统在回收或承压 |
| native allocation 调用栈 | android.heapprofd | 哪些 malloc/new 调用栈贡献了分配,哪些还没释放 |
| Java 对象保留关系 | android.java_hprof、MAT、Android Studio Profiler | 哪些 Java 对象还被谁持有 |
heapprofd 默认统计的是方向GF程向 libc malloc/free、new/delete 这类 allocator 请求的字节数。它不等于 RSS,也不覆盖所有 native backing。
GraphicBuffer、dma-buf、GPU texture、驱动侧分配、直接 mmap/memfd/ashmem 或绕过 libc malloc 的 allocator 不在默认 malloc 账里。基于 malloc 的 arena 可能只看到 arena 大块,看不到内部对象。自研 allocator 想GF这张账,可以用 heapprofd 的 custom allocator API(AHeapProfile_registerHeap 等,需要Link client 库并改分配路径),再在 heapprofd_config.heaps 里点名自定义 heap; 这属于专项投入,不是默认能力。图形内存要先看 meminfo Graphics/GL、dmabuf、GPU/graphics 计数、SurfaceFlinger / BufferQueue 关系。
heapprofd 适合补充 App、HWUI、Skia、JNI 等路径中走 malloc/new 的分配证据。
不同增长Source对应不同工具:
| 现象 | 优先工具 | heapprofd 角色 |
|---|---|---|
| Java heap 上涨,对象保留明显 | HPROF / MAT / Android Studio | 不作为第一入口 |
| Native Heap / malloc wrapper 上涨 | heapprofd | 找 malloc/new 调用栈 |
| Graphics / GL / dmabuf / Surface buffer 上涨 | meminfo、dmabuf、GPU/graphics、SurfaceFlinger | 只用于排除 App/native wrapper 是否也在分配 |
| RSS/PSS 上涨但 heapprofd 不高 | smaps_rollup、maps、mmap/syscall、dmabuf/graphics | 先拆账,不要直接判 heapprofd 抓错 |
| PSS 不涨但 RSS 涨 | smaps / file mapping / allocator cache | 先不要下泄漏结论 |
allocator 线程缓存、碎片、ZRAM、page 粒度都会让 RSS 和 heapprofd 对不上。看到 RSS 高而 heapprofd 不高时,要先考虑这些边界,不要立刻判成 heapprofd 抓错了。
Generate poster / share QR code

