本文为霍格沃兹测试学院学员学习笔记,进阶学习文末加群。
FPS 和丢帧率可以在一定程度上作为 APP 流畅度的一项衡量标准,本文介绍利用 adb shell dumpsys gfxinfo 命令获取软
本文为霍格沃兹测试学院学员学习笔记,进阶学习文末加群。
FPS 和丢帧率可以在一定程度上作为 APP 流畅度的一项衡量标准,本文介绍利用 adb shell dumpsys gfxinfo 命令获取软件渲染加载过程的数据,进行计算从而获取测试结果。
前置业务知识在此之前,需要先了解屏幕展示绘制过程及 Android 的 VSync 机制VSync 全称是 Vertical Synchronization(垂直同步),在 Android 4.1 中引入 Android 系统(同时引入的一个概念是 Triple Buffering)。
学计算机的经常听到 Buffer 的概念(生活中也碰到过很多),起到的都是一个类似的作用。用来协调两个不同速度的东西工作。
举个实例,假设显示内容和绘制使用的是用一块内存,那可能会出现下面的问题。显示有截断的异常(图中的Tear Point #1和Tear Point #2)。
为什么会这样呢?因为 CPU/GPU 处理和屏幕展示的速度不一样但是却使用的是同一块内存。
在这里插入图片描述
怎么解决呢?可以将 CPU/GPU 处理和屏幕展示分开,CPU/GPU 在后台处理,处理完一帧的数据以后才交给屏幕展示(这样可能导致另外的问题是,如果 CPU/GPU 处理很慢,那么屏幕可能会一直展示某一帧的数据,下面主要分析这个问题的处理)。
绘制过程中的两个概念。手机屏幕刷新率:手机硬件每秒刷新屏幕的次数,单位 HZ。一般是一个固定值,例如 60HZ。FPS:画面每秒传输帧数,通俗来讲就是指动画或视频的画面数。单位 HZ。手机屏幕刷新率是固定的,FPS 则是一直变化的,怎么才能保证能够运行流畅呢?从几个例子来看吧。
先解释图片代表的意思:最下面黑线代表的是时间,黄色代表屏幕展示,绿色代表 GPU 处理,蓝色代表 CPU 处理。Jank 代表的是重复展示上一帧的异常。下面会从屏幕展示的每一帧开始分析:
没有引入 VSync 机制上图是没有引入VSync 机制的处理流程。
Display 展示第0帧数据,这时 CPU/GPU 会去处理第1帧的数据。
Display 展示第1帧数据(此时屏幕显示是正常的),这时 CPU/GPU 可能处理其他任务导致很晚才去处理绘制。
因为 CPU/GPU 没处理好第2帧的数据,所以 Display 还是展示第1帧数据(此时屏幕显示是异常的),CPU/GPU 处理完第2帧没有处理完的数据然后继续处理第3帧的数据。…
上图中一个很明显的问题是,只要一次 CPU/GPU 处理出现异常就可能导致后面的一系列的处理出现异常。
引入 VSync 机制VSync 可以简单的认为是一种定时中断,系统在每次需要绘制的时候都会发送VSync Pulse 信号,CPU/GPU 收到信号后马上处理绘制。
正常情况在4.1以后引入VSync 机制。
VSync机制的绘制
在 FPS Double Buffering 异常情况
VSync 机制下 Double Buffering 时 FPS > 手机屏幕刷新率的情况。
VSync机制出现double buffering
Display 展示第A 帧数据,CPU/GPU 收到 VSync Pulse 信号马上处理B 帧的数据,但是由于计算太多,导致没有在一个 VSync 间隔内处理完。
由于第B 帧数据没有处理好,Display 继续展示第A 帧数据(此时屏幕显示是异常的)。由于系统中只存在一块内存给 CPU/GPU 处理绘制,所以在这个 VSync 间隔内cpu 不处理任何事。
Display 展示第 B 帧数据,CPU/GPU 收到 VSync Pulse 信号马上处理即将展示A 帧的数据,由于计算太多,导致没有在一个 VSync 间隔内处理完。
需要展示的A 帧数据没有处理好,Display 继续展示第 B 帧数据(此时屏幕显示是异常的)。由于系统中只存在一块内存给 CPU/GPU 处理绘制,所以在这个 VSync 间隔内 CPU 不处理任何事。…上图中一个很明显的问题是,只要出现一次Jank 就会影响下一次的VSync(cpu 不能工作)。
Triple Buffering 异常情况Triple Buffering 的引入。
VSync机制出现triple buffering
Display 展示第A 帧数据,CPU/GPU 收到VSync Pulse 信号马上处理B 帧的数据,但是由于计算太多,导致没有在一个VSync 间隔内处理完。由于第B 帧数据没有准备好,Display 继续展示第A 帧数据(此时屏幕显示是异常的)。此时虽然B 被gpu 在使用,但是cpu 可以处理Buffer C(因为有3个缓冲)。
Display 展示第B 帧数据,gpu 继续处理上一步骤的C,cpu 则处理A。后续过程出错的情况被降低了…
获取数据并计算结果1.运行命令"adb -s " deviceName " shell dumpsys gfxinfo " packageName 获取基础数据,我们会获得很多数据,这里截取需要进行分析的部分:
注:如果运行完命令发现无上图中的4个参数,则很可能是手机的“GPU呈现模式分析”未打开;
在手机的开发者选项中,找到“GPU呈现模式分析”,选择“在adb shell dumpsys gfxinfo中”,如果是华为或荣耀的手机,则选择“在屏幕上显示为线型图”:
2.如上图信息表示了每一帧在安卓系统中的四个阶段:
Draw: 表示在Java中创建显示列表部分中,OnDraw()方法占用的时间
Prepare: 准备时间
Process:表示渲染引擎执行显示列表所花的时间,view越多,时间就越长
Execute:表示把一帧数据发送到屏幕上排版显示实际花费的时间,其实是实际显示帧数据的后台缓存区与前台缓冲区交换后并将前台缓冲区的内容显示到屏幕上的时间
将上面的四个时间加起来就是绘制一帧所需要的时间,如果超过了16.67就表示掉帧了
说明Android 定义了流畅度的数据标准,以 60FPS 为标准(FPS 为每秒绘制的帧数),帧数过小就会出现卡顿感。
每一帧在安卓系统中分4个阶段,4个阶段的总和超过16.67(1秒60帧,算下来平均1帧的间隔就约是16.67ms)就认为丢帧。
这个定义在 Android6.0 以前是一定的,但是现在已经没有固定的标准了,因为目前安卓系统有3层缓存机制,加上硬件上的进步,即使超过16.67,也不一定会出现卡顿感。所以这个数据在测试时作为一种对比和相对衡量标准,也可根据需求自定义标准。
计算结果通过以上数据,就可以获取到每一帧的时间、总帧数;从而就可以计算出 jank 数、vsync 数,进而就可以得到最终的 FPS 和丢帧率数据。
当然,手工计算无疑效率低,出错率大,所以这里的计算过程最好还是以脚本形式,让代码帮我们去计算,具体代码计算原理与专项自动化过程后续探讨。
获取更多相关资料:请添加vx,ceshiren001
https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=toutiao×tamp=1653268551&author=MM
最近在做APP性能专项测试,视频剪辑过程中出现多次卡顿掉帧的问题,为了更好地了解出现掉帧卡顿的原因,去查阅了资料并记录下该文章
了解卡顿原因之前,先了解下视图渲染过程如下图:
1、CPU计算显示的内容(如文本绘制,UI布局计算,视图创建,图片解码等等),然后把计算好的内容提交给GPU
2、GPU 渲染(变换,图层合成,纹理渲染等)完成后,将渲染结果放入帧缓冲区
3、视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示
备注:
1、显示器上的所有图像都是一线一线的扫描上去的(从左到右,从上到下刷新),如下图:
3、水平同步可能会出现画面撕裂的现象(如下图)。因为画面的渲染不是整个画面一起渲染的,是逐行逐列渲染。如果没有开启垂直同步,设备配置不够,则画面在高速移动中会出现一行还没刷新完成就出现下一行,进而出现撕裂情况
4、垂直同步就是为了解决画面撕裂的问题,当开启垂直同步后,GPU 会等待显示器的 VSync 信号发出后,才进行新的一帧渲染和缓冲区更新。这样能解决画面撕裂现象,也增加了画面流畅度,但需要消费更多的计算资源,也会带来部分延迟。
5、目前,iOS设备使用双缓存,并开启垂直同步,Android是三缓存,并开启垂直同步(缓存之间怎么切换的呢???)
首先,先了解下基础的知识:假定设备的刷新率是60HZ,如果页面的滑动流畅率为60fps,也就是一秒更新60张图片,人眼上看就是流畅的效果,也就是每隔16.7ms(1/60)就要产生一帧的画面,即:每隔16.7ms发出V-SYNC信号,触发对UI进行渲染,这一帧的画面需要由CPU和GPU共同协同完成显示(详见上面的视图渲染过程)
卡顿掉帧原因:
如果在一个 VSync 时间内,CPU花费的时间比较长,留给GPU的时间就比较少,GPU+CPU总时间就可能超过16.7ms,下一帧到来前,没准备好当下帧的画面,这时候显示器还是显示上一帧的画面,就出现掉帧,就出现滑动卡顿;
同理,如果GPU花费的时间比较长,总时长也可能超过16.7ms
所以,CPU 和 GPU 不论哪个阻碍了显示流程,都会造成掉帧现象
经过上面的分析,为了优化掉帧卡顿问题,我们就需要对CPU和GPU的处理过程进行优化
先讲下以下的几个参数:
Frames Per Second;应用界面平均每秒刷新次数,
Jank :1s内卡顿次数
BigJank :1s内严重卡顿次数
PerfDog Jank计算方法:
1. 同时满足以下两条件,则认为是一次卡顿 Jank.
a) 当前帧耗时>前三帧平均耗时2倍。
b) 当前帧耗时>两帧电影帧耗时(1000ms/24 2=84ms)。
2. 同时满足两条件,则认为是一次严重卡顿 BigJank .
a) 当前帧耗时>前三帧平均耗时2倍。
b) 当前帧耗时>三帧电影帧耗时(1000ms/24 3=125ms)。
测试过程中,卡顿时长的占比。即Stutter(卡顿率)=卡顿时长/总时长
卡顿时长计算:基于Jank的基础上,一次Jank卡顿,会有一次卡顿时间Jank time。测试过程中可能有多次Jank卡顿,即有多次卡顿时间Jank time。卡顿时长即为多次卡顿时间的和
上下帧画面显示时间间隔,也可简单认为单帧渲染耗时
Avg(FTime):平均帧耗时
1、流畅度不等于FPS,需要多维度衡量,考虑FPS,Jank,Stutter
2、APP需要关注FPS、Jank及卡顿率。只是需要区分使用场景,如:
(1)、静态页面窗口
只需关注FPS,理论FPS应该为0,否则,说明有冗余刷新,容易引起手机发热及耗电。
(2) 有滚动动画页面窗口
只需关注FPS,FPS处于合适值即可,无需高频刷新。
(3)快速滑动页面窗口。
需要关注FPS、Jank及卡顿率。手机交互灵敏度就是来源于此,一般滑动状态下,帧率越高越好,Jank越小越好。
(4) 播放视频页面窗口。
需要关注FPS、Jank及卡顿率,视频卡顿直接影响用户。视频一般帧率18-24帧,Jank=0。比如微信播放视频、视频播放器等。