图像查看
- 每个竖条都是一次VSync的时间16.6ms,如果竖条宽度变宽且透明则代表超出16.6ms绘制的帧
- 每个Vsync信号来临前都会做工作(Choreographer中的postFrameCallback函数),按照顺序依次处理:INPUT 输入处理, Animation动画处理 ,Traversal 最终会调用到perfor的measure,layout,draw方法
- 每个竖条中的不同颜色代表的上面每个步骤的处理时间
颜色区分
从下到上说明
INPUT 输入处理
表示应用执行输入事件回调中的代码所花的时间。如果此区段很大,表示应用花太多时间处理用户输入。不妨考虑将此类处理任务分流到其他线程。
建议:
其实就是处理输入事件开始到结束的时间,如果竖条中此颜色高度过高代表输入事件应放到其他线程去做
Animation动画处理
表示评估运行该帧的所有动画程序所花的时间。如果此区段很大,表示您的应用可能在使用性能欠佳的自定义动画程序,或因更新属性而导致一些意料之外的工作。
建议:
该帧内运行的动画比较多
Measure,Layhout
表示在视图层次结构中 onLayout 和 onMeasure回调上所花的时间。大区段表示处理视图层次结构需要很长时间。
Measure用来确定View的宽高,当View为ViewGroup的时候还需要遍历子View,Layout在进行遍历摆放到正确的位置,当View嵌套层级变多或者自定义View时复写这两个方法时也要考虑这种情况。
Draw
表示用于创建和更新视图显示列表的时间。如果竖条的此部分很高,表明可能有许多自定义视图绘制,或 onDraw 方法执行的工作很多。
上篇文章 Vsync信号和View绘制流程的关系中说到:draw方法其实并没有进行真正的绘制,而是把绘制的内容放入到了DisplayList中接着同步到RenderThread中。放入到DisplayList的命令其实就是对canvas的操作转换而来的,该列表命令过多有两种情况:1.可用的渲染数据失效。2.canvas的操作过多
将对Canvas的操作转换成Bitmap同步至GPU
表示将位图信息上传到 GPU 所花的时间。大区段表示应用花费大量的时间加载大量图形。
draw方法调用完成后,会进行释放这块内存区域并交给RenderThread去处理渲染数据。(释放的操作在native层对应的处理是把这块内存区域变成一个Bitmap交由RenderThread去渲染)帧的所有资源都必须位于 GPU 内存中才能用来绘制帧,因此需要上传到GPU中缓存起来
要减小该值,可以采用以下技巧:
- 确保位图的分辨率不会比位图的显示尺寸大很多。应避免将 1024x1024 的图片显示为 48x48 的图片。
- 利用
prepareToDraw()
在下一个同步阶段之前异步预上传位图。
RenderThread进行调用Opengl渲染
这个显示列表就是DisplayList
表示 Android 的 2D 渲染程序向 OpenGL 发出绘制和重新绘制显示列表的命令所花的时间。此竖条的高度与执行每个显示列表所花的时间的总和成正比。显示列表越多,红色竖条就越高。
发出将显示列表绘制到屏幕上所需的全部命令所需的时间
RenderThread会执行一个DrawFrameTask的Task,里面核心方法是DrawFrame。通过OpenGl和一些库将渲染数据通知给SurefaceFliger去做图层合成。将渲染数据放入到阻塞队列中。
这个和上面的要区分开,官方文档我没看太明白,我以我的理解阐述一下吧:
绘制的耗时不代表对canvas的操作复杂,可能仅仅是逻辑处理,但是调用OpenGl渲染反映的是对canvas的操作复杂,所以一个是说OnDraw复杂,一个是说对canvas操作的复杂,在加上其实Android会进行缓存。
在某些情况下,滚动、转换或动画会要求系统重新发送显示列表,但不必实际重新构建它(即重新捕获绘制命令)。因此,您可能会看到“发出命令”条较高,但“绘制命令”条并不高。
交换缓冲区
表示 CPU 等待 GPU 完成其工作的时间。如果此竖条升高,表示应用在 GPU 上执行太多工作。
当 Android 将其所有显示列表提交给 GPU 后,系统会发出最后一条命令,告诉图形驱动程序它已完成当前帧的处理。此时,驱动程序即可将更新后的图像显示到屏幕上。
GPU提交数据给SuraceFliger让其显示,接着CPU在吧数据给到GPU进行处理,这个区间就是CPU给到GPU的时间
最后给出官方的解析:
如果 CPU 发出命令的速度快于 GPU 处理命令的速度,这两个处理器之间的通信队列就会被占满。出现这种情况时,CPU 会阻塞并等待,直到队列中有位置来放置下一个命令。这种队列占满状态通常出现在“交换缓冲区”阶段,因为此时已提交了整个帧的命令。缓解此问题的关键是降低 GPU 工作的复杂度