Code For Better 谷歌开发者之声——使用 GPU 渲染模式分析工具进行分析

2022-10-27 15:01:58 浏览数 (2)

图像查看

  • 每个竖条都是一次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 工作的复杂度

0 人点赞