屏幕渲染机制,UI性能优化,UI卡顿检测,硬件加速

Android性能优化 - 消除卡顿- https://blog.csdn.net/axi295309066/article/details/72675365

-- UI渲染流程线:
UI对象—->CPU处理为多维图形,纹理 —–通过OpeGL ES接口调用GPU—-> GPU对图进行光栅化(Frame Rate ) —->硬件时钟(Refresh Rate)—-垂直同步—->投射到屏幕
-- Android UI性能优化 检测应用中的UI卡顿- https://blog.csdn.net/lmj623565791/article/details/58626355
Android硬件加速原理与实现简介- https://tech.meituan.com/hardware-accelerate.html

-- 实现一个圆角矩形按钮通常有两种方案:

 使用PNG图片,解码PNG图片生成Bitmap,传到底层,由GPU渲染;
 使用代码(XML/Java)实现,直接将Shape信息传到底层,由GPU渲染。
-- 硬件加速的主要原理,就是通过底层软件代码,将CPU不擅长的图形计算转换成GPU专用指令,由GPU完成。
在Android中,大多数应用的界面都是利用常规的View来构建的(除了游戏、视频、图像等应用可能直接使用OpenGL ES)。
--DisplayList:
 DisplayList是一个基本绘制元素,包含元素原始属性(位置、尺寸、角度、透明度等),对应Canvas的drawXxx()方法(如下图)。
 信息传递流程:Canvas(Java API) —> OpenGL(C/C++ Lib) —> 驱动程序 —> GPU。
 在Android 4.1及以上版本,DisplayList支持属性,如果View的一些属性发生变化(比如Scale、Alpha、Translate),只需把属性更新给GPU,不需要生成新的DisplayList。
-- RenderNode:一个RenderNode包含若干个DisplayList,通常一个RenderNode对应一个View,包含View自身及其子View的所有DisplayList。

硬件加速:
 CPU更擅长复杂逻辑控制,而GPU得益于大量ALU和并行结构设计,更擅长数学运算。
 页面由各种基础元素(DisplayList)构成,渲染时需要进行大量浮点运算。
 硬件加速条件下,CPU用于控制复杂绘制逻辑、构建或更新DisplayList;GPU用于完成图形计算、渲染DisplayList。
 硬件加速条件下,刷新界面尤其是播放动画时,CPU只重建或更新必要的DisplayList,进一步提高渲染效率。

 实现同样效果,应尽量使用更简单的DisplayList,从而达到更好的性能(Shape代替Bitmap等)。

-- Android 屏幕刷新机制- https://www.cnblogs.com/dasusu/p/8311324.html
Android UI渲染机制与卡顿原理- https://blog.csdn.net/u013263323/article/details/53462724
  Android系统每隔16ms就会重新绘制一次Activity View。因为Android系统每隔16ms就会发出VSYNC信号,触发对UI进行渲染,VSYNC是Vertical Synchronization(垂直同步)的缩写,可以简单的把它认为是一种定时中断。在Android 4.1中开始引入VSYNC机制。
  渲染操作一般依赖两个核心的系统组件:CPU和GPU。 CPU主要负责Measure,Layout,Record,Execute等计算操作,GPU负责Rasterization(栅格化)操作。所谓的栅格化,就是绘制那些Button,Shape,Path,Bitmap等组件最基础的操作。它把那些组件拆分到不同的像素上进行显示,通俗点说,就是解决哪些复杂的XML布局文件和标记语言,使之转换成用户能看懂的图像,但是这不是直接转换,XML布局文件需要在CPU中首先转换为多边形或者纹理,然后再传递给GPU进行栅格化,对于栅格化,跟Opengl有关,栅格化是一个特别费时的操作。
  CPU把控件进行多边形化和纹理化,然后交给GPU进行栅格化渲染。16ms的时间主要被两件事情占用,第一件:将UI对象转换为一系列多边形和纹理;第二件:CPU传递处理数据到GPU进行栅格化,因此要缩短这两部分的时间,需要尽力减少对象转换的次数以及可能发声的问题和解决方案。
  CPU方法,最常见的性能问题是不必要的布局和失效,这些内容必须在识图层次结构中进行测量,清除并重新创建,引发这种问题通常的原因通常有两个,一个是重建显示列表的次数太多,而是花费太多时间作废视图层次并进行不必要的重绘,这两个原因在更新显示列表或者其他缓存GPU资源时资源时导致CPU工作过度。
  而GPU方法,最常见的问题就是过度绘制,通常实在像素着色过程中,通过其他工具进行后期着色时浪费了GPU处理时间。因此,对UI优化时,可以重点从以下两个方向进行:
 1.CPU产生的问题:不必要的布局和失效
 2.GPU产生的问题:过度绘制(overdraw)

深红: 意味着overdraw 4倍。像素绘制了5次或者更多,这是错误的,需要修复;
淡红: 意味着overdraw 3倍。像素绘制了4次,小范围可以接受。
绿色: 意味着overdraw 2倍。像素绘制了3次。中等大小的绿色区域是可以接受的,但是还是应该优化,减少他们。
蓝色: 意味着overdraw 1倍。像素绘制了2次。大片的啦色还是可以接受的。
优化的目标就是减少红色的Overdraw,看到更多的蓝色区域。

去掉window的背景可以在onCreate()中setContentView()之后调用getWindow().setBackgroundDrawable(null);或者在theme中添加android:windowbackground=”null”;

  在一个典型的显示系统中,一般包括CPU、GPU、display三个部分, CPU负责计算数据,把计算好数据交给GPU,GPU会对图形数据进行渲染,渲染好后放到buffer里存起来,然后display(有的文章也叫屏幕或者显示器)负责把buffer里的数据呈现到屏幕上。
  显示过程,简单的说就是CPU/GPU准备好数据,存入buffer,display每隔一段时间去buffer里取数据,然后显示出来。display读取的频率是固定的,比如每个16ms读一次,但是CPU/GPU写数据是完全无规律的。

View 的测量、布局、绘制三大流程都是交由 ViewRootImpl 发起,而且还都是在 performTraversals() 方法中发起的,所以这个方法的逻辑很复杂,因为每次都需要根据相应状态判断是否需要三个流程都走,有时可能只需要执行 performDraw() 绘制流程,有时可能只执行 performMeasure() 测量和 performLayout() 布局流程(一般测量和布局流程是一起执行的)。不管哪个流程都会遍历一次 View 树,所以其实界面的绘制是需要遍历很多次的,如果页面层次太过复杂,每一帧需要刷新的 View 又很多时,耗时就会长一点。

-- UI绘制:
 1.我们知道一个 View 发起刷新的操作时,最终是走到了 ViewRootImpl 的 scheduleTraversals() 里去,然后这个方法会将遍历绘制 View 树的操作 performTraversals() 封装到 Runnable 里,传给 Chorerographer,以当前的时间戳放进一个 mCallbackQueue 队列里,然后调用了 native 层的方法向底层注册监听下一个屏幕刷新信号事件。
 2.当下一个屏幕刷新信号发出的时候,如果我们 app 有对这个事件进行监听,那么底层它就会回调我们 app 层的 onVsync() 方法来通知。当 onVsync() 被回调时,会发一个 Message 到主线程,将后续的工作切到主线程来执行。
 3.切到主线程的工作就是去 mCallbackQueue 队列里根据时间戳将之前放进去的 Runnable 取出来执行,而这些 Runnable 有一个就是遍历绘制 View 树的操作 performTraversals()。在这次的遍历操作中,就会去绘制那些需要刷新的 View。
 4.所以说,当我们调用了 invalidate(),requestLayout(),等之类刷新界面的操作时,并不是马上就会执行这些刷新的操作,而是通过 ViewRootImpl 的 scheduleTraversals() 先向底层注册监听下一个屏幕刷新信号事件,然后等下一个屏幕刷新信号来的时候,才会去通过 performTraversals() 遍历绘制 View 树来执行这些刷新操作。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭