ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Perfetto内存泄漏实战指南:从OOM复现到火焰图归因的4步流程

Perfetto内存泄漏实战指南:从OOM复现到火焰图归因的4步流程 Perfetto内存泄漏实战指南从OOM复现到火焰图归因的4步流程【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto凌晨一点的告警com.example.pay 启动 40 分钟后 RSS 涨到 1.3GB离 OOM kill 线只剩几百 MB。我们没有等崩溃日志而是现场用 Perfetto 的 heapprofd 抓了一份 native heap profile30 分钟后把泄漏收敛到渲染线程上的一个调用点。这套命令同样适用于任何长期进程 RSS 只涨不跌的排查下面按采集、查询、判读、验证四步复盘。 采集30秒两条命令先拿两份证据先说收益两份证据回答两个不同问题。native heap profile 告诉你谁 alloc 了没 freeOOM 自动 dump 告诉你崩溃瞬间谁还活着。前者抓增量后者抓存量配合使用基本能覆盖泄漏现场。第一条抓 native 堆。仓库 checkout 里有现成脚本无 checkout 时可git clone https://gitcode.com/GitHub_Trending/pe/perfetto# 附加目标进程跑完测试路径后 Ctrl-C 停止 python3 tools/heap_profile android -n com.example.pay # 只观察 10 秒可加 -d 10000参数注意三点-n填的是进程 cmdline即adb shell ps -A最右列的名字不是包名缩写heapprofd 通过拦截malloc/free记录未释放内存的调用栈默认每 4096 字节采样一次对分配密集型进程可加大间隔降开销它不是回溯性的只记录开始追踪之后的分配所以要在分配发生前就附加上去。第二条抓 OOM 时刻的 ART 堆防止你复现窗口内没抓到# 最长等 1 小时OutOfMemoryError 抛出时自动 dump Java 堆 tools/java_heap_dump --wait-for-oom --oom-wait-seconds 3600 \ -n com.example.pay -o oome.pftrace这条命令由 ART 在OutOfMemoryError抛出瞬间触发dump 完成后直接停止追踪。更多模式Java/Kotlin 对象分配采样、非 Android Linux 支持见 memory-profiling.md。 查询三条语句把泄漏路径钉死trace 拿到手后在 Perfetto UI 的 Query(SQL) 面板里跑以下查询。更完整的写法参考 android-trace-analysis.md。这条查询回答哪条调用栈上未释放的字节最多INCLUDE PERFETTO MODULE android.memory.heap_profile.summary_tree; SELECT name, mapping_name, source_file, line_number, self_size, cumulative_size FROM android_heap_profile_summary_tree ORDER BY cumulative_size DESC LIMIT 10;结果解读cumulative_size是该函数出现在栈上任意位置的未释放总量self_size只算叶子帧。看cumulative_size排序再用source_file/line_number直接跳源码——本例第 1 行就指向渲染线程的一个缓存路径。这条查询回答泄漏窗口里哪个切片烧掉了最多 CPU 周期要求 trace 里带cpu_frequency事件INCLUDE PERFETTO MODULE linux.cpu.utilization.slice; SELECT name, thread_name, megacycles FROM cpu_cycles_per_thread_slice WHERE process_name com.example.pay AND megacycles IS NOT NULL ORDER BY megacycles DESC LIMIT 10;结果解读megacycles是运行时长乘以当时频率的积分跨频率可比。若 top 切片与堆的增量窗口时间重合说明分配热点和 CPU 热点是同一函数改一处收益加倍。看图要点视线落在排名最靠上的那条 slice 上它是该进程烧掉周期最多的操作本例中它与堆增量曲线的时间段完全重叠确认了同一热点的判断。如果泄漏在 Java 侧用第三条INCLUDE PERFETTO MODULE android.memory.heap_graph.heap_graph_class_aggregation; SELECT type_name, obj_count, size_bytes, reachable_size_bytes FROM android_heap_graph_class_aggregation ORDER BY reachable_size_bytes DESC LIMIT 10;结果解读reachable_size_bytes是存活对象的总量两次 dump 相减就是净增长top 类如果持续增长且 GC 后不回落优先查静态集合和监听器没解绑。 判读一张阈值表加一张火焰图拿到数字后按这张表分级阈值可按业务基线调整指标正常区间告警阈值处置方向单区间 retained/allocated 比20%50%切火焰图 Unreleased 模式找只分配不释放的栈Top 1 调用点占未释放总量15%30%泄漏集中直接按line_number改代码reachable_size_bytes每 10 分钟净增5MB50MB 且 GC 后不回落查 top 类的静态持有链泄漏窗口 top slicemegacycles50M500M确认分配热点与 CPU 热点是否同一函数火焰图默认按未释放字节聚合越靠近底部越贴近malloc()调用点看图要点眼睛落在图中底部区域最宽的那根横条它离malloc()最近、代表最大的泄漏路径本例该条明显宽于同层其他路径点开即可看到完整调用链与查询里的source_file互相印证。深入排查思路可对照 case-studies/memory.md。 验证修复前后对比的三个数字修复后重跑同一套采集命令、同一个 30 分钟窗口只对比三个数指标修复前修复后判定native 堆 retained30min profile212MB9MB泄漏路径消除RSS 增速~55MB/min1MB/min回到正常水位同窗口 top slicemegacycles410M18M分配热点同步消除本例改动只有一处渲染线程的回调里补上了free。如果三个数里只有 retained 降了、RSS 增速没变说明还有第二条路径回到查询篇第 3 条语句查 Java 侧。非 Android Linux 环境的 heapprofd 细节见 native-heap-profiler.md。✅ 交接前自检清单heapprofd 在目标分配发生之前就已附加它不记录历史分配profile 时长覆盖至少 2 个 GC 周期增量有周期性可观察Top 1 调用点占比未超 30% 时已切换 Unreleased Count 模式排查小对象泄漏火焰图的line_number能映射回可执行的源码行OOM dominator 树与 native profile 交叉验证过Java 侧和 native 侧可能各自在漏回归版本的 retained、RSS 增速、megacycles三个数已留档对比【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表