a284628487 / AndroidPoint

Android Note
1 stars 0 forks source link

GUP rendering #7

Open a284628487 opened 6 years ago

a284628487 commented 6 years ago

https://developer.android.com/studio/profile/inspect-gpu-rendering

a284628487 commented 6 years ago

Android 包含一些设备上开发者选项,可直观地了解您的应用在何处出现界面渲染问题,比如执行太多不必要的渲染工作,或执行长时间的线程和GPU操作。

分析 GPU 的渲染速度

Profile GPU Rendering工具以滚动直方图的形式直观地显示渲染界面窗口帧所花费的时间(以每帧16毫秒的速度作为对比基准)。

在性能较低的 GPU 上,可用的填充率(GPU 填充帧缓冲区的速度)可能很低。 随着绘制帧所需的像素数增加,GPU 可能需要花较长时间来处理新命令,并要求系统的其余任务等待,直到系统可以跟上需求。 此分析工具可帮助您确定 GPU 何时因尝试绘制像素而负担过重,或何时因大量的过度绘制而被拖累。

启用分析器

开发者选项:Monitoring -> Profile GUP Rendering,选择On screen as bars在设备屏幕上叠加图表显示。

图表内容:

  1. 沿水平轴的每个竖条都代表一个帧,每个竖条的高度表示渲染该帧所花的时间(单位:毫秒)。
  2. 水平绿线表示16毫秒。要实现每秒60帧,代表每个帧的竖条需要保持在此线以下。当竖条超出此线时,可能会使动画出现暂停。
  3. 此工具通过加宽对应的竖条并降低透明度来突出显示超出 16 毫秒阈值的帧。
  4. 每个竖条都有与渲染管道中某个阶段对应的彩色区段。区段数因设备的 API 级别而异。

Android 6.0及更高版本上,每个竖条区块多达8条,从上到下分别是:

  1. 交换缓冲区 表示 CPU 等待 GPU 完成其工作的时间。 如果此竖条升高,则表示应用在 GPU 上执行太多工作。
  2. 命令问题 表示 Android 的 2D 渲染器向 OpenGL 发起绘制和重新绘制显示列表的命令所花的时间。此竖条的高度与它执行每个显示列表所花的时间的总和成正比—显示列表越多,红色条就越高。
  3. 同步和上传 表示将位图信息上传到 GPU 所花的时间。大区段表示应用花费大量的时间加载大量图形。
  4. 绘制 表示用于创建和更新视图显示列表的时间。此条段代代表绘制工作,也即对应于 onDraw 方法。
  5. 测量/布局 表示在视图层次结构中的 onLayout 和 onMeasure 回调上所花的时间。 大区段表示此视图层次结构正在花很长时间进行处理。
  6. 动画 表示评估运行该帧的所有动画程序所花的时间。如果此区段很大,则表示您的应用可能在使用性能欠佳的自定义动画程序,或因更新属性而导致一些意料之外的工作。
  7. 输入处理 表示应用执行输入 Event 回调中的代码所花的时间。如果此区段很大,则表示此应用花太多时间处理用户输入。考虑将此处理任务分流到另一个线程。
  8. 其他时间/VSync 延迟 表示应用执行两个连续帧之间的操作所花的时间。它可能表示界面线程中进行的处理太多,而这些处理任务本可以分流到其他线程。

Android 6.0以下

  1. 表示 CPU 等待 GPU 完成其工作的时间。 如果此竖条升高,则表示应用在 GPU 上执行太多工作。
  2. 表示 Android 的 2D 渲染器向 OpenGL 发起绘制和重新绘制显示列表的命令所花的时间。此竖条的高度与它执行每个显示列表所花的时间的总和成正比—显示列表越多,红色条就越高。
  3. 表示将位图信息上传到 GPU 所花的时间。大区段表示应用花费大量的时间加载大量图形。此区段在运行 Android 4.0 或更低版本的设备上不可见。
  4. 表示用于创建和更新视图显示列表的时间。如果竖条的此部分很高,则表明这里可能有许多自定义视图绘制,或 onDraw 函数执行的工作很多。

分析 GUP 过度绘制

当在同一帧中相同像素被多次绘制时,便会发生过度绘制。因此此图可显示您的应用可能在何处执行太多不必要的渲染工作,这可能是 GPU 多此一举地渲染用户不可见的像素所导致的性能问题。

开发者选项:Hardware accelearated rendering -> Debug GUP Overdraw中选择Show overdraw areas

界面颜色表示的含义:

  1. 真彩色: 没有过度绘制
  2. 蓝色: 过度绘制 1 次
  3. 绿色: 过度绘制 2 次
  4. 粉色: 过度绘制 3 次
  5. 红色: 过度绘制 4 次或更多

fixing

  1. 移除不必要的背景.
  2. 减少View层级.
  3. 减少带透明度的View(带透明度的像素点相比其它不透明的像素点,至少要两次绘制).

Reduce transparency

带透明度的绘制,和标准绘制(系统将隐藏已经绘制好的像素点,直接在该像素点上面绘制另一个不透明的像素)不同, 带透明度的物体的绘制,需要先把已经存在的像素绘制出来,然后再绘制透明度,实现混合效果。 Link

使用 Profile GUP Rendering 工具进行分析

Input handling

Animation

Measurement/layout

Draw

Sync/upload

Sync/upload表示Bitmap从CPU内存空间上传到GPU内存空间所花费的时间。CPU和GPU使用的是不同的内存区域,所以图片需要进行传递。 绘制一个图片的流程:在GUP绘制一个图片之前,系统需要先将图片信息传递到GPU内存区,然后GPU会将图片缓存起来, 避免再次绘制的时候需要再次传递图片数据造成时间消耗,之后才能渲染绘制到屏幕当中。

由于每一帧画面的所有的资源都需要在GPU内存区域当中,所以如果有大量的小的资源,或者少量的大的资源的情况下,都会导致上传时间过长, 比如app显示了一张和屏幕差不多大小的图片,或者app显示了大量的小图片。

两种提升措施:

  1. 避免使用不合适的分辨率的图片,图片分辨率不要大于它要显示到的目标区域的分辨率。
  2. 使用prepareToDraw()方法,异步预先上传图片资源。

prepareToDraw()

图片必须上传到GPU内存之后才能进行绘制,通常这是在图片第一次被绘制的时候才进行的操作,但是上传操作有一定的耗时。 Android N之后才有的api,该方法将在RenderThread中启动一个异常上传任务将图片上传到GPU内存,如果图片已经上传过,则不做处理。 提前调用这个方法,可以节约一定的时间,推荐这样使用:在worker线程中将图片解码完成之后,直接调用该方法(也是在worker线程)。

[Link](https://developer.android.com/reference/android/graphics/Bitmap#prepareToDraw())

Issue commands

Process/swap buffers

Miscellaneous

Profile GPU Rendering

尽管此工具名为 Profile GPU Rendering,但所有受监控的进程实际上发生在 CPU 中。通过将命令提交到 GPU 触发渲染,GPU 异步渲染屏幕。 在某些情况下,GPU 会有太多工作要处理,在它可以接收新命令前,CPU 必须进入等待状态。 在等待时,您将看到橙色条和红色条中出现峰值,且命令提交将被阻止,直到 GPU 命令队列腾出更多空间。

Link

a284628487 commented 6 years ago

Diagnose view hierarchy issues

  1. Systrace 查看系统性能,定位是否有绘制帧的时候有性能问题。
  2. Profile GPU rendering 查看View绘制时间,以及是否有过度绘制。
  3. Lint Analyze -> Inspect Code可以分析出布局文件中可以优化的地方。
  4. Layout Inspector 布局检查器工具提供了应用程序视图层次结构的可视化表示。

Solve view hierarchy issues

Remove redundant nested layouts

尽量减少冗余View层级。

Lint工具可以帮助标记此问题,从而减少调试时间。

Adopt merge/include

使用 <merge> 标签或者 <include> 标签。

Adopt a cheaper layout

选择合适的 layout 布局,比如使用 ConstraintLayout 替换 RelativeLayout

Link