注册

你真的了解Systrace吗?


欢迎关 Android茶话会 在技术学习、个人成长的道路上,让我们一起前进!



一、什么是SysTrace?


在日常开发中有时候遇到棘手的性能问题就需要使用这个工具,Systrace 是 「Android 4.1」 中新增的性能数据采样和分析工具。它可帮助开发者收集 Android 关键子系统
(如 SurfaceFlinger/SystemServer/Kernel/Input/Display 等 Framework 部分关键模块、服务,View」系统等 的运行信息,从而帮助开发者更直观的「分析系统瓶颈,改进性能」image.png


二、如何使用SysTrace?


2.1 采集trace


首先我们需要了解Trace的采集主要涉及几部分:采集方式、自定义trace阶段、Release包抓取Trace和系统Trace类同异步调用的差异;


命令行采集:



  • 设备要求**「Android 4.3 (API level 18)及以上」**
  • 命令如下:python systrace.py [options][「categories」],示例如下:

python /Users/yangzhiyong/Library/Android/sdk/platform-tools/systrace/systrace.py -t 10 -o trace.html gfx input view sched freq wm am hwui workq res dalvik sync disk load perf hal rs idle mmc -a com.ss.android.lark.debug

# -o : 指示输出文件的路径和名字
# -t : 抓取时间(最新版本可以不用指定, 按 Enter 即可结束),单位为秒
# -b : 指定 buffer 大小 (一般情况下,默认的 Buffer 是够用的,如果你要抓很长的 Trae , 那么建议调大 Buffer )
# -a : 指定 app 包名 (如果要 Debug 自定义的 Trace 点, 记得要加这个)



  • 查看支持的categories



    • adb shell atrace --list_categories
    • python systrace.py -l



// 粗体部分是常用的categories;
         gfx - Graphics
       input - Input
        view - View System
     webview - WebView
          wm - Window Manager
          am - Activity Manager
          sm - Sync Manager
       audio - Audio
       video - Video
      camera - Camera
         hal - Hardware Modules
         res - Resource Loading
      dalvik - Dalvik VM
          rs - RenderScript
      bionic - Bionic C Library
       power - Power Management
          pm - Package Manager
          ss - System Server
    database - Database
     network - Network
         adb - ADB
    vibrator - Vibrator
        aidl - AIDL calls
         pdx - PDX services
       sched - CPU Scheduling
        freq - CPU Frequency
        idle - CPU Idle
        disk - Disk I/O
        sync - Synchronization
  memreclaim - Kernel Memory Reclaim
  binder_driver - Binder Kernel driver
  binder_lock - Binder global lock trace

系统自带工具:




  • 设备要求**「Android 9(API level 28)及其以上」**




  • 开发者模式->系统跟踪




  • trace导出:



    • 通知栏分享;
    • adb pull /data/local/traces/ .
    • systrace --from-file .ctrace .perfetto-trace 转换成html



网页版采集分析工具:💻



  • 设备要求**「Android 10(API level 29)及其以上;」**
  • Perfetto UI



除此之外还有一些常用的技巧





  1. 自定义TAG

image.png 具体使用可参考:developer.android.com/topic/perfo…




  • 「定义」



    • 在事件开始调用Trace.beginSection(event);
    • 在事件结束调用Trace.endSection(),需成对调用;



  • 「使用」 添加了自定义TAG后,需要-a指定包名参数,才可以采集到自定义的trace信息;





  1. Release包抓取trace

反射调用setAppTracingAllowed即可:


try {
    Class threadClazz = Class.forName("android.os.Trace");
    Method setAppTracingAllowed = threadClazz.getDeclaredMethod("setAppTracingAllowed"boolean.class);
    setAppTracingAllowed.invoke(nulltrue);
catch (Exception e) {
    e.printStackTrace();
}

3. 同异步trace的差异


「同步」「异步」「区别」
beginSection(@NonNull String sectionName)beginAsyncSection(@NonNull String methodName, int cookie)异步调用需要传methodName及cookie,开始结束匹配更准确,且不用B-A-A-B类似嵌套,不过该接口为隐藏接口,需反射调用,可使用SystemTracer类;
endSection()endAsyncSection(@NonNull String methodName, int cookie)

2.2 分析


拿到这些trace 我们如何分析也是一个重要的部分


2.2.1 Trace文件打开


首先是打开这个文件



  1. chrome://tracing:推荐:不过近期版本该工具对trace中线程、进程名解析不出来,不利于查看;
  2. ui.perfetto.dev/#!/: 推荐,不过新版分析工具不支持VSync的高亮;
  3. perfetto.bytedance.net/#!/viewer: 不推荐,仅支持单进程查看,对于涉及系统调用的分析不方便;

较早版本sysTrace生成的html文件浏览器即可打开,但最近版本已无法正常打开,需要通过chrome工具手动加载;


2.2.2 面板区域说明


image.png


image.png



  1. 用户屏幕交互
  2. CPU 使用率
  3. CPU各核心的运行情况
  4. 进程信息
  5. 进程变量/进程
  6. 选中区段的详细信息
  7. 鼠标操作选项,可通过1-4快速切换
  8. 进程过滤
  9. VSync高亮配置

2.2.3 常用快捷键


比较常用的快捷键是W S A D M V;



  • W : 放大 Systrace,放大可以更好地看清局部细节
  • S : 缩小 Systrace,缩小以查看整体
  • A : 左移
  • D : 右移
  • M : 高亮选中当前鼠标点击的段(这个比较常用,可以快速标识出这个方法的左右边界和执行时间,方便上下查看)
  • V : 高亮VSync的时机,方便分析掉帧的原因;

image.png


image.png


2.2.4 线程状态


a) 线程状态

「线程状态」「Systrace中的显示」「说明」
绿色 : 运行中(Running)image.png我们经常会查看 Running 状态的线程,查看其运行的时间,与竞品做对比,分析快或者慢的原因
蓝色 : 可运行(Runnable)image.pngRunnable 状态的线程状态持续时间越长,则表示 cpu 的调度越忙,没有及时处理到这个任务
白色 : 休眠中(Sleep)image.png一般是在等事件驱动
橘色 : 不可中断的睡眠态 IO Block(Uninterruptible Sleep WakeKill)image.png一般是标示 IO 操作慢,如果有大量的橘色不可中断的睡眠态出现,那么一般是由于进入了低内存状态
紫色 : 不可中断的睡眠态(Uninterruptible Sleep)image.png一般是陷入了内核态,有些情况下是正常的,有些情况下是不正常的,需要按照具体的情况去分析

b) 线程唤醒

一个任务在进入 Running 状态之前,会先进入 Runnable 状态进行等待,而 Systrace 会把这个状态也标示在 Systrace 上; image.pngimage.png stateWhenDescheduled定义:chromium.googlesource.com/external/tr…


c) 线程参数说明


  • Wall Duration:函数执行的总耗时
  • CPU Duration:在 CPU 上执行的耗时
  • Self Time:自身执行的总耗时,不包括子方法
  • CPU Self Time:自身在 CPU 上执行的耗时,不包括子方法

d) 函数调用虚实区别

如下图,我们看到标识setUpHWComposer调用的紫色条并不是实心的,实心的部分代表CPU Duration相对于Wall Duration的占比: image.png


2.2.5 CPU信息


image.png


image.png



  1. C-State

为了在CPU空闲的时候降低功耗,CPU可以被命令进入low-power模式。每个CPU都有几种power模式,这些模式被统称为C-states或者C-modes; C-States从C0开始,C0是CPU的正常工作模式,CPU处于100%运行状态。C后的数越高,CPU睡眠得越深,CPU的功耗被降低得越多,同时需要更多的时间回到C0模式。


「C-State」「描述」
C-0RUN MODE,运行模式。
C-1STANDBY,就位模式,随时准备投入运行
C-2DORMANT,休眠状态,被唤醒投入运行时有一定的延迟
C-3SHUTDOWN,关闭状态,需要有较长的延迟才能进入运行状态,减少耗电


  1. Clock Frequency:CPU当前运行频率;
  2. Clock Frequency Limits:CPU最大最小频率,通过该参数可以判断CPU核心差异,如大中小核

2.2.6 常见系统进程、线程




  • 进程




    • system_server



      • AMS
      • WMS
      • SurfaceFlinger





  • 线程



    • UI Thread //主线程
    • Render Thread //渲染线程
    • Binder Thread //跨进程调用线程



2.2.7 常见问题


a) 「锁等待」

image.png「monitor contention」 with owner 「caton_dump_stack (11056)」 waiters=0 blocking from 「boolean android.os.MessageQueue.enqueueMessage(android.os.Message, long)(MessageQueue.java:544)」 image.png 结合代码看,这段信息的意思是,「caton_dump_stack」线程(线程ID是11056)作为「owner」持有了主线程消息队列对象锁,「waiters」表示等待在该对象锁上的其他线程数(不包括当前线程),所以总的有1个线程等待对象锁释放,当前线程等待的位置是「enqueueMessage调用处」


b) 「SurfaceFlinger绘制」

SurfaceFlinger主要是收集各个UI渲染层的数据合成发送给Hardware Composer;一般应用的渲染层包括状态栏、应用页面、导航栏,每个部分都是单独渲染生成Buffer的,基本步骤如下:



  1. 应用收到VSYNC-app信号后,在**「UI Thread」完成数据计算;准备好后,将数据发送到「RenderThread」**;
  2. 应用在**「RenderThread」完成数据渲染后,将数据填充到「SurfaceFlinger」**的对应页面BufferQueue中;
  3. 在**「SurfaceFlinger」收到VSYNC-sf信号后,「SurfaceFlinger」** 会遍历它的层列表的BufferQueue,以寻找新的缓冲区。如果找到新的缓冲区,它会获取该缓冲区;否则,它会继续使用以前获取的缓冲区。「SurfaceFlinger」 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略;
  4. **「SurfaceFlinger」**向 「HWC」 提供一个完整的层列表,并询问“您希望如何处理这些层?”
  5. 「HWC」 的响应方式是将每个层标记为叠加层或 GLES 合成;
  6. 「SurfaceFlinger」 会处理所有 GLES 合成,将输出缓冲区传送到 「HWC」,并让 「HWC」 处理其余部分;

image.png


image.png


c) 「掉帧」

上一部分描述了SurfaceFlinger合成每帧数据的过程,在上述过程中,如果**「UI Thread」计算不及时,或者「RenderThread」渲染不及时,或者「BufferQueue」**中可用Buffer不足导致在下一次VSYNC信号来临之前,没有准备好需要显示的帧的数据,就会出现丢帧,Systrace 报告列出了渲染界面帧的每个进程,并指明了沿时间轴渲染的每个帧。在 16.6 毫秒内渲染的必须保持每秒 60 帧稳定帧速率的帧会以绿色圆圈表示。渲染时间超过 16.6 毫秒的帧会以黄色或红色帧圆圈表示:



  1. 绿色:未丢帧;
  2. 棕色:轻微丢帧,丢1帧 ;
  3. 红色:严重丢帧,丢大于1帧;

image.png 通过Systrace右上角的View Options > Highlight VSync,我们可以高亮VSYNC信号到来的时刻,需要注意的是,高亮的VSYNC主要是VSYNC-app信号(可在SurfaceFlinger进程中查看),且灰白相间的位置是VSYNC信号到来的时刻。 如下图,显示了丢1帧的情况,第二个VSYNC到来时,主线程仍未完成显示帧数据的计算,所以出现丢帧的问题。 image.png


三、常见trace工具对比


其实我们分析trace不光只有系统这一种方法,下图做个简单的总结


「工具名」「类型」「原理」「优缺点」「使用场景」「使用说明」
Traceviewinstrument利用 Android Runtime 函数调用的 event 事件,将函数运行的耗时和调用关系写入 trace 文件中。「优点:」 全函数调用分析;「缺点:」 工具本身带来的性能开销过大,有时无法反映真实的情况。比如一个函数本身的耗时是 1 秒,开启 Traceview 后可能会变成 5 秒,而且这些函数的耗时变化并不是成比例放大;- 线下- 整个程序执行流程的耗时已废弃,之前DDMS有相关工具入口
Nanoscopeinstrument直接修改 Android 虚拟机源码,在ArtMethod执行入口和执行结束位置增加埋点代码,将所有的信息先写到内存,等到 trace 结束后才统一生成结果文件。「优点:」- 全函数调用分析;- 性能开销小;- 可以支持分析任意一个应用,可用于做竞品分析;「缺点:」- 需要自己刷 ROM,并且当前只支持 Nexus 6P,或者采用其提供的 x86 架构的模拟器;- 默认只支持主线程采集,其他线程需要代码手动设置;- 线下- 整个程序执行流程的耗时github.com/uber/nanosc…
systracesample实际是其他工具的封装,Systrace使用atrace开启追踪,然后读取ftrace的缓存,并且把它重新转换成HTML格式。「优点:」- 可以看到整个流程系统和应用程序的调用流程。包括系统关键线程的函数调用,例如渲染耗时、线程锁,GC 耗时等;- 性能损耗可以接受;「缺点:」- 不支持应用程序代码的耗时分析;需手动添加或者编译期插装;- 线下- 分析系统调用developer.android.com/topic/perfo…
Simpleperfsample利用 CPU 的性能监控单元(PMU)提供的硬件 perf 事件。「优点:」- 支持Native分析;- 性能开销非常低;「缺点:」- Java分析对Android版本要求比较高;- 线下- 分析 Native 代码的耗时android.googlesource.com/platform/sy… 在 Android M 和以前,Simpleperf 不支持 Java 代码分析。- 在 Android O 和以前,需要手动指定编译 OAT 文件。- 在 Android P 和以后,无需做任何事情,Simpleperf 就可以支持 Java 代码分析;
Profiler(CPU Profiler)混合- Sample Java Methods 的功能类似于 Traceview 的 sample 类型;- Trace Java Methods 的功能类似于 Traceview 的 instrument 类型;- Trace System Calls 的功能类似于 systrace;- Sample Native (API Level 26+) 的功能类似于 Simpleperf;「优点:」- 集成在IDE中,操作简单;「缺点:」- 性能开销大,应用明显卡顿;- 无法用于自动化测试等场景;- 线下developer.android.com/studio/prof…

「instrument」:获取一段时间内所有函数的调用过程,可以通过分析这段时间内的函数调用流程,再进一步分析待优化的点。


「sample」:有选择性或者采用抽样的方式观察某些函数调用过程,可以通过这些有限的信息推测出流程中的可疑点,然后再继续细化分析。


作者:Android茶话会
来源:juejin.cn/post/7238172236185354297

0 个评论

要回复文章请先登录注册