ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Android性能剖析:从systrace到perfetto的系统级跟踪实战指南

Android性能剖析:从systrace到perfetto的系统级跟踪实战指南 1. 项目概述为什么我们需要systrace与perfetto在Android应用和系统性能优化的战场上性能问题往往像幽灵一样难以捉摸。应用启动慢了一拍列表滑动偶尔掉帧或者后台服务莫名耗电这些现象背后是CPU调度、图形渲染、锁竞争、IO阻塞等一系列复杂系统行为的综合结果。作为一名开发者如果只盯着自己应用的代码无异于盲人摸象。你需要一双能透视整个Android系统运行状态的“眼睛”这就是systrace和它的继任者perfetto。简单来说systrace和perfetto是Android平台最核心的系统级性能剖析工具。它们不是用来分析某个函数耗时的Profiler而是记录系统在特定时间段内发生的所有关键事件并将这些事件以时间线的形式可视化出来。你可以看到每个CPU核心上正在运行哪个线程、线程在等待什么锁、SurfaceFlinger何时进行合成、Binder调用了多久、甚至电量管理模块何时进入了休眠状态。通过这张宏观的“交响乐谱”你能精准定位出是哪个“乐手”进程/线程在哪个“小节”时间点出了问题导致整场“演出”用户体验卡顿。atrace是systrace数据采集的命令行前端而perfetto则是Google推出的新一代、功能更强大的全平台跟踪解决方案正在逐步取代传统的systrace。掌握它们意味着你拿到了从系统层面根治性能顽疾的“手术刀”。无论是应用开发、系统框架开发还是驱动调试这都是不可或缺的硬核技能。2. 工具选型解析atrace(systrace) 与 perfetto 的定位与抉择在开始动手之前我们必须理清atrace代表systrace和perfetto的关系与区别这决定了你后续工作流的选择。很多人会混淆这里彻底讲明白。2.1 atrace 与 systrace 的关系首先明确一个概念我们常说的“抓取systrace”这个动作通常是通过atrace命令来完成的。atrace是Android系统中的一个命令行工具它的作用是启用和配置内核及系统服务的跟踪点tracepoints并将跟踪数据写入缓冲区。而systrace.py是一个Python脚本位于Android SDK的platform-tools/systrace目录下它实际上是一个封装好的自动化脚本。它的工作流程是通过ADB连接设备。在设备上执行atrace命令并指定要抓取的类别如gfx,view,sched。将atrace输出的原始数据流抓取到本地。调用python的trace2html模块将原始数据转换为可视化的HTML网页。所以atrace是底层的数据采集器systrace是包含采集、转换、可视化的一整套前端工具链。我们说的“使用systrace”默认指的就是使用systrace.py这个脚本。2.2 perfetto 的革新与优势Perfetto是Google在Android 10API 29中正式引入并逐渐成为Android 11推荐使用的下一代系统跟踪框架。它并非systrace的简单升级而是一个全新的、更强大的体系。核心优势对比特性维度atrace (systrace)perfetto架构基于Linux内核的ftrace上层通过atrace封装。全新的、高性能的用户态和内核态跟踪守护进程traced支持更多数据源。数据源主要依赖内核ftrace扩展性有限。原生支持ftrace并集成heap profiling内存堆分析、native memory dumps、Android Logcat、电源管理事件等是真正的“一站式”平台。配置方式命令行参数相对简单但功能有限。强大的TraceConfig协议缓冲区protobuf配置可以极其精细地控制跟踪时长、缓冲区大小、数据源开关、触发条件等。跟踪时长通常用于短时间如5-10秒的跟踪。支持超长时间跟踪数小时甚至数天数据会滚动写入磁盘用于分析间歇性、难以复现的问题。可视化生成独立的HTML文件在Chrome浏览器中打开chrome://tracing。使用更现代的Perfetto UI在线网址ui.perfetto.dev或本地部署界面更友好分析功能更强大如SQL查询跟踪数据。开销相对较低。设计目标就是高性能、低开销即使长时间开启对系统影响也极小。 注意从Android 12开始systrace脚本底层实际上已经调用perfetto来捕获ftrace数据了。但为了兼容性和操作习惯systrace.py这个入口依然保留。如何选择新手入门、快速抓取从systrace.py开始语法简单上手快能满足大部分UI性能分析如卡顿、掉帧的需求。深度分析、复杂场景必须使用perfetto。例如需要分析内存增长、跟踪native代码、进行长时间功耗记录、或者需要复杂的触发条件时。Android 11 设备强烈建议直接学习并使用perfetto这是未来的方向。3. 环境准备与基础配置工欲善其事必先利其器。无论使用哪种工具都需要准备好基础环境。3.1 开发机环境准备安装Pythonsystrace.py是一个Python 2.7/3.x脚本确保你的开发机Windows/Mac/Linux已安装Python并已添加到环境变量PATH中。安装Android SDK Platform-Tools这是必须的因为它包含了ADBAndroid Debug Bridge和systrace脚本。如果你使用Android Studio它通常已自动安装。你也可以从 Android开发者官网 单独下载。 将platform-tools目录的路径添加到系统的PATH环境变量中以便在终端中直接使用adb和systrace.py命令。安装Chrome浏览器用于可视化systrace生成的HTML文件chrome://tracing。Perfetto UI也推荐使用Chrome打开。3.2 设备端配置跟踪功能需要设备端的支持并且通常需要开启开发者选项和USB调试。启用开发者选项在设备的“设置”-“关于手机”中连续点击“版本号”7次。开启USB调试进入“设置”-“系统”-“开发者选项”找到“USB调试”并开启。可选的设备端设置针对非Root设备对于systrace在“开发者选项”中找到“监控”或“调试”类别确保“启用跟踪”或类似的选项是开启的。有些厂商设备可能需要额外开启“GPU渲染模式分析”等。对于perfettoPerfetto服务traced在Android 9上默认运行。为了允许非Root的ADB连接进行跟踪你需要开启一个额外的开关adb shell setprop persist.traced.enable 1执行后重启设备。这个设置允许通过ADB使用perfetto。 重要提示在生产环境或用户设备上抓取trace尤其是长时间抓取可能会涉及隐私和性能问题。务必在测试设备上进行并告知相关方。3.3 连接与验证使用USB线连接设备和开发机在终端执行adb devices如果看到设备序列号后面显示device则表示连接成功。这是所有后续操作的基础。4. 使用 atrace 和 systrace.py 进行跟踪这是最经典、最常用的快速抓取方式特别适合分析动画、列表滑动、应用启动等场景的卡顿。4.1 systrace.py 命令行实战systrace.py命令的基本语法如下python systrace.py [options] [categories...]它位于android-sdk/platform-tools/systrace/目录下。为了方便我们可以进入该目录执行或将此目录加入PATH。一个最常用的抓取UI性能trace的命令示例cd /path/to/android-sdk/platform-tools/systrace python systrace.py -t 5 -o my_trace.html gfx view sched freq idle am wm让我们拆解这个命令-t 5指定跟踪时间为5秒。你需要在命令执行后立即在设备上操作你想分析的应用例如快速滑动列表。5秒后trace会自动停止并生成文件。-o my_trace.html指定输出文件名为my_trace.html。gfx view sched freq idle am wm这是跟踪类别categories决定了采集哪些系统事件。这是命令的核心。gfx图形相关事件包括SurfaceFlinger、VSYNC、应用UI线程的绘制等。分析卡顿必选。viewView系统事件如measure、layout、draw。schedCPU调度信息。必选可以看到每个线程在哪个CPU核心上运行、何时被切换出去。freqCPU频率变化。idleCPU空闲状态。amActivity Manager事件如Activity启动、生命周期。wmWindow Manager事件。执行流程在终端输入上述命令并回车。终端会显示Starting tracing (5 seconds)并开始倒计时。立即切换到你的测试设备开始执行你想要分析的操作例如从桌面点击应用图标启动或者在一个列表页面疯狂滑动。倒计时结束终端显示Tracing completed. Collecting output...最后是Output written to: my_trace.html。用Chrome浏览器打开my_trace.html文件。4.2 关键类别Categories详解选择正确的类别组合至关重要。抓取过多类别会导致文件巨大、加载缓慢抓取过少可能会遗漏关键信息。核心必备类别schedCPU调度。没有它你无法分析线程是否因为锁或IO而阻塞也无法看到CPU利用率。这是分析任何性能问题的基石。gfx图形系统。包含VSYNC信号、SurfaceFlinger合成、应用渲染线程等。分析掉帧、卡顿的利器。viewAndroid View系统。可以看到performTraversals即measure/layout/draw的执行情况。常用扩展类别am/wm分析应用启动速度、页面跳转时非常有用。input跟踪触摸、按键等输入事件的处理流程。freq/idle分析功耗和热问题时看CPU是否降频或进入深度休眠。binder_driver查看Binder IPC调用分析跨进程通信延迟。disk/mmc分析IO读写性能问题。查看所有可用类别python systrace.py -l这个命令会列出当前连接设备支持的所有跟踪类别。不同设备、不同系统版本支持的类别可能不同。4.3 atrace 命令直接使用systrace.py底层调用了atrace。你也可以直接使用adb shell atrace命令这在一些自动化脚本或需要更精细控制时有用。基本用法adb shell atrace -t 5 -c -o /data/local/tmp/trace_output gfx view sched-c在跟踪结束后清空清除缓冲区。-o指定设备上的输出文件路径。抓取完成后你需要将文件拉取到本地并使用systrace.py或perfettoUI进行转换和查看。adb pull /data/local/tmp/trace_output . python systrace.py --from-filetrace_output -o my_trace.html 实操心得直接使用atrace命令的一个好处是你可以编写脚本在应用执行特定操作时通过am命令启动Activity等自动开始和结束跟踪实现自动化性能测试。5. 使用 perfetto 进行高级跟踪Perfetto提供了两种主要的使用方式通过命令行工具perfetto和通过Web UIui.perfetto.dev进行配置和抓取。这里我们重点介绍更强大、更推荐的后一种方式。5.1 通过 Perfetto Web UI 抓取 Trace这是最简单直观的方式无需记忆复杂命令。打开Web UI在Chrome中访问 https://ui.perfetto.dev 。录制新Trace点击左侧边栏的**“Record new trace”**。连接设备在“Recording settings”页面确保你的设备通过USB连接并在“Android devices”下拉框中被识别。如果未发现检查adb devices和persist.traced.enable属性。配置Trace参数Recording mode选择“Stop when full”或“Long trace”。前者适用于短时间抓取类似systrace后者用于长时间记录数据会滚动保存到文件。Max duration/Buffer size设置最大时长和内存缓冲区大小。对于短时间分析5-10秒缓冲区256MB通常足够。Probes (数据源)这是核心配置区。你可以按需勾选atrace勾选这个并在下方展开“Android apps svcs”选择你需要atrace类别如gfx,view,sched这相当于systrace的功能。ftrace更底层的Linux内核跟踪可以勾选sched/sched_switch线程切换等事件。Java heap graphs抓取Java堆内存分配信息用于内存分析。Memory snapshots捕获native内存快照。Power电源管理相关事件。Logcat同时抓取系统日志便于交叉分析。开始录制点击右上角的“Start recording”按钮。操作设备像使用systrace一样立即在设备上进行你想要分析的操作。停止并下载操作完成后回到Web UI点击“Stop”。Perfetto会自动处理数据并下载一个.perfetto-trace或.pftrace文件。分析下载完成后该文件会自动在同一个Web UI中打开你可以开始进行分析。5.2 使用 perfetto 命令行工具对于自动化集成或在无图形界面的环境中命令行工具是必须的。你需要获取perfetto可执行文件它通常包含在Android SDK的platform-tools目录下或者可以从 Perfetto GitHub 源码编译。步骤准备配置文件Perfetto的强大之处在于其基于protobuf的配置文件trace_config.pb或文本格式的trace_config.textproto。你可以从Web UI导出配置或手动编写。 一个简单的文本格式配置文件示例 (config.textproto)duration_ms: 5000 buffers: { size_kb: 32768 fill_policy: DISCARD } data_sources: { config { name: linux.ftrace ftrace_config { ftrace_events: sched/sched_switch ftrace_events: sched/sched_wakeup ftrace_events: irq/irq_handler_entry } } } data_sources: { config { name: android.systrace systrace_config { trace_categories: gfx trace_categories: view trace_categories: sched } } }这个配置抓取5秒的trace包含ftrace的调度事件和atrace的gfx/view/sched事件。执行抓取命令adb push config.textproto /data/local/tmp/ adb shell perfetto -c /data/local/tmp/config.textproto -o /data/local/tmp/trace.pftrace或者更简单的一行命令通过--txt指定文本配置adb shell echo -e duration_ms: 5000\nbuffers { size_kb: 32768 }\ndata_sources { config { name: \android.systrace\ systrace_config { trace_categories: \gfx view sched\ } } } | perfetto -c - --txt -o /data/local/tmp/trace.pftrace拉取Trace文件adb pull /data/local/tmp/trace.pftrace .用Perfetto UI打开这个.pftrace文件进行分析。 注意事项命令行方式需要你对protobuf配置有一定了解。建议先从Web UI配置并导出配置文件然后基于导出的文件进行修改这样学习成本最低。6. Trace文件分析与解读实战抓取到trace文件.html或.pftrace只是第一步更重要的是从中读出问题。这里以Perfetto UI为主进行讲解其功能远超旧的Chrome Tracing。6.1 Perfetto UI 核心界面与操作打开trace文件后你会看到如下主要区域时间线概览区Overview顶部显示整个trace的时间范围可以缩放和拖拽。轨道区Tracks主体部分每个水平行是一个“轨道”展示一个实体如CPU、进程、线程、计数器随时间的变化。CPU轨道显示每个CPU核心的使用情况不同颜色代表不同的进程/线程。进程/线程轨道显示每个线程的状态运行Running、可运行Runnable、休眠Sleeping、不可中断休眠Uninterruptible Sleep等。这是分析卡顿最关键的区域。计数器轨道如CPU频率、内存用量、帧率SurfaceFlinger等。事件轨道显示特定事件如VSYNC、Binder事务等。工具栏提供选择S、移动M、时间选择T、测量I等工具。查询框Query (SQL)Perfetto最强大的功能之一允许你用SQL查询trace数据。例如查询所有耗时超过5ms的Binder事务。基本操作技巧缩放鼠标滚轮或使用W放大、S缩小键。移动按住Shift鼠标拖拽或使用A左移、D右移键。选择与测量按I键进入测量模式在时间线上拖动可以测量两点间的时间差。查看详情点击任何一段色块或事件下方会弹出详情面板Current Selection显示该事件的名称、耗时、参数等信息。6.2 定位卡顿的通用分析流程假设我们遇到了列表滑动卡顿的问题分析流程如下定位卡顿时间点在轨道区上方的时间线上找到帧率计数器FPS突然下降或出现断层的区域用I键框选这个区域放大查看。观察UI线程状态找到你的应用进程如com.example.myapp展开它找到主线程通常是main或包名同名的线程。在卡顿时间段内观察主线程的状态条。如果主线程长时间是Running绿色说明CPU正在密集执行你的代码。你需要点击该绿色块查看详情面板中的“Stack Trace”如果抓取时启用了应用层符号。这能告诉你具体是哪个函数/方法耗时最长。如果主线程长时间是Runnable蓝色或Sleeping灰色说明它准备好了但没被CPU执行或者在等待如锁、IO。这是典型的线程调度问题。分析CPU调度立刻去看对应时间点的CPU轨道。如果所有CPU核心都处于繁忙状态绿色块密集且运行着其他进程的线程说明系统整体负载高你的应用线程抢不到CPU时间片。这可能是因为后台有大量任务。如果CPU有闲置空白但你的主线程仍是蓝色Runnable这非常反常可能遇到了优先级反转或CPU频率限制thermal throttling。此时可以查看freq和idle轨道确认。检查锁竞争如果主线程状态显示为Uninterruptible Sleep (D)这通常意味着它在等待IO。但如果是在等待锁在sched和lock事件中会有体现。Perfetto的“Slices”轨道可能会显示MonitorWait等锁事件。检查渲染流水线展开SurfaceFlinger进程和你的应用RenderThread。查看VSYNC信号vsync_*是否规律。如果VSYNC间隔不稳定可能是底层显示问题。查看应用RenderThread的DrawFrame切片。如果两个DrawFrame之间的间隔远大于16.6ms60Hz说明渲染一帧的时间过长。查看SurfaceFlinger的Composition切片。如果合成耗时过长可能是图层太多或过于复杂。6.3 使用SQL查询进行深度挖掘Perfetto UI内置了一个强大的SQL查询引擎。点击左侧边栏的“Query (SQL)”即可打开。一些实用的查询示例查找耗时最长的Binder调用SELECT slice.name, dur / 1e6 as dur_ms, thread.name as thread_name FROM slice JOIN thread_track ON slice.track_id thread_track.id JOIN thread USING (utid) WHERE slice.name LIKE ‘binder%‘ AND dur 1e6 -- 查找耗时超过1ms的binder事务 ORDER BY dur DESC LIMIT 10;统计所有线程在Runnable状态的总时间SELECT thread.name, sum(dur) / 1e6 as total_runnable_ms FROM thread_state JOIN thread USING (utid) WHERE state ‘R‘ -- ‘R‘ 代表 Runnable GROUP BY thread.name ORDER BY total_runnable_ms DESC;查找因锁等待导致的调度延迟这需要抓取时启用了sched和lock相关的事件。查询可能比较复杂但思路是关联sched_wakeup事件和线程实际开始运行的时间差。 实操心得对于复杂的性能问题不要只盯着UI线程。一个后台网络线程持有了UI线程需要的锁或者一个Bitmap解码任务在异步线程占满了CPU都可能导致UI卡顿。学会在Perfetto中全局地、关联地看问题是进阶的关键。7. 常见问题与排查技巧实录在实际使用中你肯定会遇到各种问题。这里记录了一些典型场景和解决方法。7.1 抓取失败或数据为空现象执行命令后生成的HTML文件打开是空白或只有零星信息。排查检查类别首先用python systrace.py -l确认你选择的类别在设备上是否支持。有些定制ROM可能移除了某些跟踪点。检查权限确保设备已开启USB调试并且电脑已被授权。尝试adb root需要工程机或userdebug版本系统后再抓取权限最高。检查atrace状态在设备shell中执行adb shell atrace --list_categories看是否能列出类别。执行adb shell atrace -c -t 1 gfx看是否有输出。尝试基础类别先只用sched和gfx这两个最核心、支持最广的类别抓取看是否有数据。对于perfetto确保persist.traced.enable已设置为1并重启。7.2 Trace文件巨大浏览器卡死现象抓取时间长或类别过多生成几百MB的HTML文件Chrome无法加载。解决控制抓取时长和类别只抓取问题发生的核心时段如3-5秒只选择必要的类别。使用Perfetto UIPerfetto UIui.perfetto.dev对大型trace文件的处理能力远强于Chrome Tracing。将.html文件转换为.pftrace格式Perfetto UI支持导入或用Perfetto直接抓取。使用命令行过滤对于perfetto可以在配置文件中使用filter字段或者在抓取后使用perfetto命令行工具进行过滤和裁剪。7.3 看不到应用层函数调用栈Stack Trace现象在trace中点击线程的Running切片详情面板中没有“Stack Trace”或显示为[unknown]。解决需要带符号的Debug包要看到Java/Kotlin函数名必须使用未混淆的Debug版本应用。Release包通常被ProGuard/R8混淆函数名无意义。对于systrace在命令中添加-a package_name选项。例如python systrace.py -t 5 -a com.example.myapp -o trace.html gfx view sched。这会将应用进程的跟踪标记关联起来。对于Perfetto在Web UI配置的“Android apps svcs”下勾选你的应用包名。或者在配置文件的android.systrace数据源中设置target_pid或target_cmdline。Native符号要看到C/C的函数名需要将设备的/system/lib等库的符号表或你的so文件的调试符号加载到Perfetto UI中。这通常需要从编译设备的系统镜像中获取。7.4 如何分析应用启动性能应用启动是典型的性能分析场景。抓取配置抓取类别必须包含amActivity Manager和wmWindow Manager。命令示例python systrace.py -t 10 -a com.example.myapp -o startup.html am wm gfx view sched.抓取时机在命令开始倒计时后立即点击应用图标。确保trace覆盖从点击到首页完全加载的完整过程。分析关键路径在Perfetto UI中搜索“launching”或“startActivity”事件找到你的应用启动的起点。顺着时间线向右看关注am轨道ActivityThread的performLaunchActivity、handleResumeActivity等事件。你的应用进程和主线程查看main线程在Activity.onCreate、onStart、onResume期间做了什么。是否有长时间的RunningCPU计算或Sleeping等待IO/锁gfx轨道查看第一帧的DrawFrame和SurfaceFlinger合成何时完成。从点击图标到第一帧显示在屏幕上的时间就是用户感知的启动时间。7.5 自动化集成与进阶技巧对于需要持续集成CI的性能测试手动抓取是不现实的。脚本化抓取使用atrace# 开始抓取 adb shell “atrace -c -b 32768 -t 15 gfx view sched wm am -o /data/local/tmp/auto_trace ” # 执行自动化操作例如启动应用 adb shell am start -W -n com.example.myapp/.MainActivity # 等待抓取结束简单方法sleep 比跟踪时间长一点 sleep 16 # 拉取文件并转换 adb pull /data/local/tmp/auto_trace . python systrace.py --from-fileauto_trace -o auto_trace.html脚本化抓取使用perfetto编写一个trace_config.textproto文件然后使用adb shell perfetto -c ...命令在自动化脚本中调用。这更加强大和稳定。使用Android Studio Profiler对于应用开发Android Studio内置的Profiler提供了更友好的systrace集成。你可以在CPU Profiler中直接点击“Record System Trace”按钮它底层也是调用perfetto/systrace但提供了与应用代码更好的关联。掌握systrace和perfetto就像是获得了Android系统的“时光机”和“显微镜”。它让你能从纷繁复杂的现象背后直指性能问题的本质——是计算太慢是等待太久还是调度不公。最初的学习曲线可能有些陡峭但一旦你成功用它定位并解决了一个棘手的线上卡顿问题那种成就感会让你觉得所有投入都是值得的。从今天开始不要再靠猜来优化性能让数据说话。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表