Traceview / Systrace 的基础操作
Traceview
https://developer.android.google.cn/studio/profile/generate-trace-logs?hl=zh-cn#java
1 | Debug.startMethodTracing("sample"); |
Device File Explorer中可以找到trace文件,直接打开,可以看到火焰图
Traceview 已弃用。如果您使用的是 Android Studio 3.2 或更高版本,应改为使用 CPU 性能分析器来执行
- 事件时间轴
显示应用中的 activity 在其生命周期内不断转换经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。 - CPU 时间轴
显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。此时间轴还会显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的 CPU 使用率进行对比。您可以通过沿时间轴的横轴方向移动鼠标来检查历史 CPU 使用率数据。 - 线程活动时间轴
列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录轨迹后,您可以从此时间轴上选择一个线程,以在轨迹窗格中检查其数据。
- 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,线程处于正在运行或可运行状态。
- 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
- 灰色:表示线程正在休眠且没有消耗任何 CPU 时间。 当线程需要访问尚不可用的资源时,就会出现这种情况。在这种情况下,要么线程主动进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用。
TraceView试图收集某个阶段所有函数的运行信息,开销过大
Systrace的思路是反过来的,在不清楚问题的情况下,通过假设-分析-验证 的过程找出问题
Systrace
https://zhuanlan.zhihu.com/p/27331842
- 进入systrace目录:
cd /Users/stew/Library/Android/sdk/platform-tools/systrace - 执行命令:
./systrace.py -t 10 sched gfx view wm am app webview -a - 生成trace.html目录:
/Users/stew/Library/Android/sdk/platform-tools/systrace - 在chrome中查看trace.html
chrome://tracing/trace.html - 操作:
W : 放大 Systrace , 放大可以更好地看清局部细节
S : 缩小 Systrace, 缩小以查看整体
A : 左移
D : 右移
M : 高亮选中当前鼠标点击的段
Systrace 是对 Linux Kernel中 ftrace 的封装
内核部分:Systrace 利用了 Linux Kernel 中的 ftrace 功能
数据采集部分:Android 定义了一个 Trace 类。应用程序可利用该类把统计信息输出给ftrace。同时,Android 还有一个 atrace 程序,它可以从 ftrace 中读取统计信息然后交给数据分析工具来处理
数据分析工具:Android 提供一个 systrace.py
线程状态主要有下面几个
- 绿色 : 运行中(Running)
只有在该状态的线程才可能在 cpu 上运行 - 蓝色 : 可运行(Runnable)
线程可以运行但当前没有安排,在等待 cpu 调度
作用:Runnable 状态的线程状态持续时间越长,则表示 cpu 的调度越忙,没有及时处理到这个任务 - 白色 : 休眠中(Sleep)
线程没有工作要做,可能是因为线程在互斥锁上被阻塞。
作用 : 这里一般是在等事件驱动 - 橘色 : 不可中断的睡眠态 (Uninterruptible Sleep - IO Block)
线程在I / O上被阻塞或等待磁盘操作完成 - 紫色 : 不可中断的睡眠态(Uninterruptible Sleep)
一般是陷入了内核态,有些情况下是正常的,有些情况下是不正常的,需要按照具体的情况去分析
应用的启动动画由 Launcher 和应用自己的第一帧组成,点击图标启动应用的时候,由于 App 还在启动,Launcher 首先启动一个 StartingWindow,等 App 的第一帧绘制好了之后,再切换到 App 的窗口动画
与 AMS 相关的 Trace 一般会用 TRACE_TAG_ACTIVITY_MANAGER 这个 TAG,在 Systrace 中的名字是 ActivityManager
与 WMS 相关的 Trace 一般会用 TRACE_TAG_WINDOW_MANAGER 这个 TAG,在 Systrace 中 WindowManagerService 在 SystemServer 中多在对应的 Binder 中出现,在 Window 的各种场景一般都会有对应的 Trace 点来记录,比如大家熟悉的 relayoutWIndow、performLayout、prepareToDisplay 等
Input 是 SystemServer 线程里面非常重要的一部分,主要是由 InputReader 和 InputDispatcher 这两个 Native 线程组成
android.bg,BackgroundThread 在系统中使用比较多,许多对性能没有要求的任务,一般都会放到 BackgroundThread 中去执行
App 部分 -> BufferQueue 部分 -> SurfaceFlinger 部分 -> HWComposer 部分
App 部分
1)Vsync 信号的接收和处理
2)RenderThread 的 dequeueBuffer
dequeue 有出队的意思,dequeueBuffer 顾名思义,就是从队列中拿出一个 Buffer,这个队列就是 SurfaceFlinger 中的 BufferQueue。
3)RenderThread 的 queueBuffer
queue 有入队的意思,queueBuffer 顾名思义就是讲 Buffer 放回到 BufferQueue,App 处理完 Buffer 后(写入具体的 drawcall),会把这个 Buffer 通过 eglSwapBuffersWithDamageKHR -> queueBuffer 这个流程,将 Buffer 放回 BufferQueueBufferQueue 部分
dequeue、queue、acquire、releaseSurfaceFlinger 部分
收到 Vsync 信号后开始工作,MessageQueue::INVALIDATE主要是执行 handleMessageTransaction 和 handleMessageInvalidate 这两个方法,MessageQueue::REFRESH — 主要是执行 handleMessageRefresh 方法HWComposer 部分
1)SurfaceFlinger 向 HWC 提供一个完整的层列表,并询问“您希望如何处理这些层?”
2)HWC 的响应方式是将每个层标记为叠加层或 GLES 合成。
3)SurfaceFlinger 会处理所有 GLES 合成,将输出缓冲区传送到 HWC,并让 HWC 处理其余部分。
Input
InputReader 和 InputDispatcher 是跑在 SystemServer 里面的两个 Native 线程,负责读取和分发 Input 事件
Vsync
Vsync Offset 我们指的是 VSYNC_APP 和 VSYNC_SF 之间有一个 Offset,即上图中 phase-sf - phase-app 的值,这个 Offset 是厂商可以配置的。如果 Offset 不为 0,那么意味着 App 和 SurfaceFlinger 主进程不是同时收到 Vsync 信号,而是间隔 Offset (通常在 0 - 16.6ms 之间)
目前大部分厂商都没有配置这个 Offset,所以 App 和 SurfaceFlinger 是同时收到 Vsync 信号的.
android studio terminal中执行:adb shell dumpsys SurfaceFlinger
结果截取:可见offset=0
app phase: 1000000 ns SF phase: 1000000 ns
early app phase: 1000000 ns early SF phase: 1000000 ns
GL early app phase: 1000000 ns GL early SF phase: 1000000 ns
next VSYNC threshold: 9223372036854775807 ns
present offset: 0 ns VSYNC period: 16666666 ns
不是每次申请 Vsync 都会由硬件产生 Vsync,只有此次请求 vsync 的时间距离上次合成时间大于 500ms,才会通知 hwc,请求 HW_VSYNC
HW_VSYNC 主要是利用最近的硬件 VSYNC 来做预测,最少要 3 个,最多是 32 个,实际上要用几个则不一定, DispSync 拿到 6 个 VSYNC 后就会计算出 SW_VSYNC,只要收到的 Present Fence 没有超过误差,硬件 VSYNC 就会关掉,不然会继续接收硬件 VSYNC 计算 SW_VSYNC 的值,直到误差小于 threshold.