ARTICLE DETAIL

资讯详情

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

如何用 Perfetto 系统追踪 5 步定位卡顿与内存异常:Android 性能排查实战指南

如何用 Perfetto 系统追踪 5 步定位卡顿与内存异常:Android 性能排查实战指南 如何用 Perfetto 系统追踪 5 步定位卡顿与内存异常Android 性能排查实战指南【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto灰度放量到 20% 后第 3 分钟应用的 P99 帧耗时从 18ms 跳到 61ms10 分钟内该页面进程的 RSS 又涨了 120MB。卡顿和内存增长同时出现分不清谁因谁果。我们用一个 Perfetto 追踪会话把两边串起来排查最后收成一条可复用的诊断路径。 三步递进排查从内存增长到锁竞争内存 10 分钟涨了 120MB先在堆侧排除泄漏打开 trace 后先切到 heapprofd 生成的火焰图heapprofd 是 Perfetto 的原生堆采样器按调用栈归属每一笔 malloc度量项选Unreleased malloc sizedump 时刻分配了还没释放的字节数。火焰图里TexturePool.acquire这一层明显最宽但肉眼看不出它是否随时间膨胀——把窗口切回 SQL用聚合查询确认这段 SQL 把未释放的分配按顶层帧聚合用来判断增长集中在哪条代码路径上。SELECT stack_profile_callsite.name AS top_frame, SUM(size) AS unreleased_bytes, SUM(count) AS unreleased_count FROM heap_profile_allocation JOIN stack_profile_callsite USING (callsite_id) WHERE size 0 GROUP BY top_frame ORDER BY unreleased_bytes DESC LIMIT 10;结果里排前三的顶层帧全部在纹理缓存路径且未释放字节数从追踪前 60 秒到后 60 秒只增加了约 4%而同一窗口 RSS 的增量几乎全部来自文件映射区。也就是说这 120MB 里真正漏的部分不足 10MB主体是纹理缓存预热堆侧可以结案。读图提示看最顶层的宽帧——帧宽在时间上保持稳定、只是整体偏宽对应的是稳定缓存而不是持续增长真正要盯的是宽度随采样推进不断变宽的帧。62% 的丢帧是 Buffer Stuffing卡顿不全在算得慢堆侧排除了泄漏嫌疑把镜头切到帧侧。FrameTimeline 是 SurfaceFlinger 里的丢帧检测模块Android 12每帧都会带一个jank_type标注卡顿类型。先用 SQL 看类型分布决定往哪边查这段查询统计目标应用丢帧的类型占比区分帧算不完和帧发太早堆在队列里。SELECT jank_type, COUNT(*) AS frame_count, AVG(dur) / 1e6 AS avg_dur_ms FROM actual_frame_timeline_slice WHERE process.name com.example.im GROUP BY jank_type ORDER BY frame_count DESC;62% 的丢帧是 Buffer Stuffing应用在前一帧还没上屏时就提交了新帧帧在 BufferQueue 里排队导致延迟增加但帧率看着还顺剩下约三分之一是 AppDeadlineMissed帧确实没在 vsync 截止时间内算完。这两类的处理方向完全不同前者要查提帧节奏后者才需要进 CPU 路径。读图提示选中一条红色切片后看详情面板里的jank_type和present_type字段这是该帧卡顿的定性结论红色表示丢帧责任方就是该进程。红帧的主线程被一个后台线程挡了 15ms挑一条 AppDeadlineMissed 红帧放大主线程状态轨道里有一段 15ms 的 Runnable→Running 等待远超正常水平。光看时序不知道它在等谁这一步把采样触发点从定时器换成调度事件本身在sched/sched_switch和sched/sched_waking上各挂一份 linux.perf 采样分别是线程被换出、线程唤醒别的线程的瞬间period: 1表示不抽样、每次事件都抓调用栈并用 tracepoint 过滤只保留目标进程避免全系统每秒两万次调度事件把缓冲区打爆这段配置在调度阻塞和唤醒两个精确时刻抓调用栈而不是按时间随机采样。data_sources { config { name: linux.perf perf_event_config { timebase { period: 1 tracepoint { name: sched/sched_switch filter: prev_comm ~ \*ImMain*\ || next_comm ~ \*ImMain*\ } } callstack_sampling { kernel_frames: true } ring_buffer_pages: 2048 } } }回放 trace 后主线程阻塞点的调用栈显示它卡在ReentrantLock.lock上尝试入队一个延迟任务顺着该线程 Running 切片上的 woken-by 链路点过去唤醒它的是一个只跑了 160us 的后台工作线程。也就是说主线程等的不是那 160us而是锁队列里排在这名线程前面的一串后台线程。读图提示把眼睛落在调用栈轨道的彩色小三角和 woken-by 链接上它们分别标出线程在哪被换出和谁把它唤醒两条调用栈合起来就能锁定锁的持有者。把过滤条件扩到全部后台线程后阻塞窗口内的每个后台线程调用栈都收敛到同一把执行器锁的 acquire/release锁竞争嫌疑坐实后台线程数量多解锁后按入队顺序逐个唤醒优先级更高的主线程反而排在长队后面这就是典型的优先级反转放大效应。完整排查过程可对照 官方调度阻塞案例 复盘。读图提示看左侧多个后台线程的调用栈——如果它们全在同一把锁的获取和释放上反复出现锁队列排队就是主线程阻塞的放大器。⚙️ 生产环境追踪配置环形缓冲区与 tracepoint 怎么开上面三个环节用到的数据源在生产监控里可以合并进一份 TraceConfig。选 256MB 的 RING_BUFFER 是因为帧分析和调度采样都会产生突发写入环形策略保证超限时丢弃最旧数据而保留事发窗口ftrace 只开sched/sched_switch而不挂 perf 高频采样把开销压到可长期开启的水平。这份配置开启调度事件、帧时间线与进程元信息三类数据源是卡顿归因场景的基线参数。buffers: { size_kb: 262144 fill_policy: RING_BUFFER } data_sources { config { name: linux.ftrace ftrace_config { ftrace_events: sched/sched_switch atrace_categories: gfx atrace_categories: view } } } data_sources { config { name: android.surfaceflinger.frametimeline } } data_sources { config { name: linux.process_stats process_stats_config { scan_all_processes_on_start: true } } }分析场景传统手段Perfetto 方案差异点卡顿归因logcat 打点人工拼时间线FrameTimeline 自动标注 jank_type丢帧直接归因到 App / SurfaceFlinger / HAL锁竞争加日志或 gdb 抓现场sched_switch/waking 精确调用栈采样能拿到唤醒方的调用栈定位锁持有者内存泄漏dump 后人工比对快照heapprofd 火焰图按调用栈归属精确到函数级别区分缓存与泄漏读图提示上方 CPU 利用率轨道与下方进程切片按时间对齐利用率尖峰和某条业务切片重合时那条切片就是下一轮优化的对象。 从 trace 到结论5 步诊断决策路径打开 trace看进程 RSS 曲线与 heapprofd 火焰图先排除或坐实内存泄漏查actual_frame_timeline_slice的 jank_type 分布判断丢帧主因在应用侧还是 SurfaceFlinger 侧放大红帧看线程状态轨道的 woken-by 链路确认阻塞主线程的线程用 sched_switch/sched_waking 采样抓阻塞方与唤醒方调用栈锁定锁持有者修复后复测对比 P99 帧耗时前后变化归档 trace 作基线。这条路径依赖内核 tracepoint需要 debug 版系统或 root 权限纯应用内逻辑问题如算法复杂度、业务分支系统层追踪提供的信息有限需要搭配 ART 堆 dump 与 in-app tracing 补充。【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表