0%

面试题-Android显示机制以及 Systrace 的使用

一、屏幕刷新机制

简单来说,屏幕刷新包括三个步骤:CPU计算、GPU进一步处理和缓存、最后display 再将缓存(buffer)中的数据显示出来

Screen Tearing(撕裂)

在早期设备上,采用单缓冲模式,由于 display 的处理频率是固定的,而CPU/GPU 处理数据的时间不确定,因此,会有屏幕撕裂的情况:

屏幕撕裂

从上图可看出,由于 CPU/GPU 仅完成部分工作,因此,在 0.015s 时,屏幕上部分显示的是2画面,下部分显示的是 1 画面的撕裂画面。

Double-buffer

双缓冲技术,原理就是采用2个 buffer,一块 back buffer 用于 CPU/GPU 后台绘制,另一块 framebuffer 则用于显示,当 back buffer 准备就绪之后,才进行交换,这样就避免了屏幕撕裂。

VSync

在 Android 4.1 之前,没有采用 VSync 信号,此时 CPU 或 GPU 往 buffer 中写数据比较随意,因此会造成丢帧:

无VSync造成丢帧

当扫描完一个屏幕后,设备需要重新回到第一行以进入下一次循环,此时有一段时间空隙,这个时间点就是我们进行缓冲区交换的最佳时间。

在 Android 4.1 之后,Android display 系统进行了重构(黄油计划:Project Butter),引入三个核心元素: VSync、Triple Buffer 以及 Choreographer,它规定一旦收到 VSync 通知(约16ms触发一次),CPU 和 GPU 就立刻开始工作把显示数据写入 buffer。根据 VSync 新来来同步处理数据,让 CPU/GPU 有完整的 16ms 时间来处理数据,减少 jank。

Triple Buffer

双缓存机制并不完美,当 CPU/GPU 工作时间较长时,会出现如下情况:

双缓冲下的jank

从图可以看出,当 CPU/GPU 的处理时间超过 16ms 时,第一个 VSync 信号来了,缓冲区 B 还没准备好,于是只能继续显示 A 缓冲区的内容,而在 B 完成后又因为第2个 VSync 信号还没来,不能及时展示,只能等待下一个 VSync 信号到来,在这一过程中,有一大段时间是被浪费的

三缓冲虽然不能解决双缓冲第一次 jank 问题,但是当第一次 VSync 发生后,CPU 不用再等待了,它会使用第三个buffer C 来进行下一帧的准备工作。虽然对缓冲区 C 的处理所需时间也超狗 16ms ,但并不影响显示屏——第2次 VSync 到来时,会选择 buffer B 进行展示,而第 3 次 VSync 时,会接着采用 C ,而不是像 double buffer 时只能再显示一遍 B ,这样就有效地减低了 jank,如下图所示:

三缓冲示意图

App 相关的屏幕绘制

总的来说,当有屏幕刷新操作时(是否时invalidate ?),系统会将 View 树的测量、布局和绘制等封装到一个 Runnable(当然,会过滤掉同一帧内的重复调用) ,然后监听 VSync 信号,待信号来时再触发此 Runnable。

卡顿分析利器——Systrace 工具

systrace 的使用

一般来说,系统很多关键地方都添加了 trace ,可以看到很多关键代码耗时,当然,我们自己也可以自定义(叫做添加自己的 Label):

1
2
3
4
Trace.beginSection("名称"):
//doSomething

Trace.endSection():

一般来说,添加自己的 Label 需要注意以下几点:

  • begin 和 end 必须成对出现
  • Label 支持嵌套,但是 begin 会找最近的 end
  • begin 和 end 必须在同一线程
  • 抓取 systrace 时,必须指定包名

但是,还有一种情况,那就是 异步trace,使用方法如下:

1
2
3
4
5
6
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);

//dosomeThing

Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);

Systrace 文件获取

Android 在 platform-tools 中提供了 systrace 文件获取的工具,这是一个 python 脚本,用命令行就能够获取:

python systrace.py –help

一般来说,我们只需要使用 -o ,-b, -t,-a 对应输出文件路径,buffersize,time,需要分析的应用程序包名。

查看trace 文件

使用 chrome 打开导出的 trace 文件,大概如下图所示:

trace文件分析

重点关注带 F 的原点,表示一帧,只有圆点为绿色时才表示这一帧没有超过 16ms ,其他颜色都是大于 16ms ,红色表示严重超时。

异步 trace

以上内容参考自CSDN上的博客简书上的博客

谢谢你的鼓励