界面卡顿Jank与FPS获取
2015-11-24 22:08
260 查看
1 VSYNC 的概念
VSYNC(Vertical Synchronization)是一个相当古老的概念,对于游戏玩家,它有一个更加大名鼎鼎的中文名字—-垂直同步。
“垂直同步(vsync)”指的是显卡的输出帧数和屏幕的垂直刷新率相同,这完全是一个CRT显示器上的概念。其实无论是VSYNC还是垂直同步这个名字,因为LCD根本就没有垂直扫描的这种东西,因此这个名字本身已经没有意义。但是基于历史的原因,这个名称在图形图像领域被沿袭下来。
在当下,垂直同步的含义我们可以理解为,使得显卡生成帧的速度和屏幕刷新的速度的保持一致。举例来说,如果屏幕的刷新率为60Hz,那么生成帧的速度就应该被固定在1/60 s。
1.1 Android中的VSYNC
从Android 4.1开始,谷歌致力于解决Android系统中最饱受诟病的一个问题,滑动不如iOS流畅。因谷歌在4.1版本引入了一个重大的改进—Project Butter,也即是黄油计划。
Project Butter对Android Display系统进行了重构,引入了三个核心元素,即VSYNC、Triple Buffer和Choreographer。这里我们重点讲解VSYNC的作用。
这个图中有三个元素,Display是显示屏幕,GPU和CPU负责渲染帧数据,每个帧以方框表示,并以数字进行编号,如0、1、2等等。VSync用于指导双缓冲区的交换。
以时间的顺序来看下将会发生的异常:
Step1. Display显示第0帧数据,此时CPU和GPU渲染第1帧画面,而且赶在Display显示下一帧前完成。
Step2. 因为渲染及时,Display在第0帧显示完成后,也就是第1个VSync后,正常显示第1帧。
Step3. 由于某些原因,比如CPU资源被占用,系统没有及时地开始处理第2帧,直到第2个VSync快来前才开始处理。
Step4. 第2个VSync来时,由于第2帧数据还没有准备就绪,显示的还是第1帧。这种情况被Android开发组命名为“Jank”。
Step5. 当第2帧数据准备完成后,它并不会马上被显示,而是要等待下一个VSync。
所以总的来说,就是屏幕平白无故地多显示了一次第1帧。原因大家应该都看到了,就是CPU没有及时地开始着手处理第2帧的渲染工作,以致“延误军机”。
其实总结上面的这个情况之所以发生,首先的原因就在于第二帧没有及时的绘制。我们将在三重缓冲一节中再讲解这种情况)。那么如何使得第二帧即使被绘制呢?
这就是我们在Graphic系统中引入VSYNC的原因,考虑下面这张图:
如上图所示,一旦VSync出现后,立刻就开始执行下一帧的绘制工作。这样就可以大大降低Jank出现的概率。另外,VSYNC引入后,要求绘制也只能在收到VSYNC消息之后才能进行,因此,也就杜绝了另外一种极端情况的出现—-CPU(GPU)一直不停的进行绘制,帧的生成速度高于屏幕的刷新速度,导致生成的帧不能被显示,只能丢弃,这样就出现了丢帧的情况—-引入VSYNC后,绘制的速度就和屏幕刷新的速度保持一致了。
经过上面的介绍,希望读者对Jank 和VSYNC有所认识。下面将说明怎么来得到FPS和卡顿Jank帧数。
2 Jank 和 FPS
我们只关注present time。
2.1 计算Janky frames
这里的frame duration是有present time两两相减得到的。
由上图可以得到jank 帧,右下角。
2.2 FPS
帧率(FPS)由present time的最后一帧减去第一帧得到时间值,然后除以帧数得到。
3 自动化获取
自动化思路:使用python 结合uiautomator,根据配置信息,启动想评测的app,操作app(滑动,放大等等),打印surfaceflinger数据出来,稍微处理一下即可得到fps和掉帧数。
步骤:
(1)清理历史数据
○ adb shell dumpsys SurfaceFlinger --latency-clear <window name>
(2)使用uiautomator操作某个APP
○ fling, scroll, zoom
(3)根据2操作,打印数据
○ adb shell dumpsys SurfaceFlinger --latency <window name>
(4)处理数据
如读者会使用Python的话,直接按照上面几步即可得到FPS和Jank 数,因为逻辑已经很清晰了。本人写的代码较多,这里不附上说明。
VSYNC(Vertical Synchronization)是一个相当古老的概念,对于游戏玩家,它有一个更加大名鼎鼎的中文名字—-垂直同步。
“垂直同步(vsync)”指的是显卡的输出帧数和屏幕的垂直刷新率相同,这完全是一个CRT显示器上的概念。其实无论是VSYNC还是垂直同步这个名字,因为LCD根本就没有垂直扫描的这种东西,因此这个名字本身已经没有意义。但是基于历史的原因,这个名称在图形图像领域被沿袭下来。
在当下,垂直同步的含义我们可以理解为,使得显卡生成帧的速度和屏幕刷新的速度的保持一致。举例来说,如果屏幕的刷新率为60Hz,那么生成帧的速度就应该被固定在1/60 s。
1.1 Android中的VSYNC
从Android 4.1开始,谷歌致力于解决Android系统中最饱受诟病的一个问题,滑动不如iOS流畅。因谷歌在4.1版本引入了一个重大的改进—Project Butter,也即是黄油计划。
Project Butter对Android Display系统进行了重构,引入了三个核心元素,即VSYNC、Triple Buffer和Choreographer。这里我们重点讲解VSYNC的作用。
这个图中有三个元素,Display是显示屏幕,GPU和CPU负责渲染帧数据,每个帧以方框表示,并以数字进行编号,如0、1、2等等。VSync用于指导双缓冲区的交换。
以时间的顺序来看下将会发生的异常:
Step1. Display显示第0帧数据,此时CPU和GPU渲染第1帧画面,而且赶在Display显示下一帧前完成。
Step2. 因为渲染及时,Display在第0帧显示完成后,也就是第1个VSync后,正常显示第1帧。
Step3. 由于某些原因,比如CPU资源被占用,系统没有及时地开始处理第2帧,直到第2个VSync快来前才开始处理。
Step4. 第2个VSync来时,由于第2帧数据还没有准备就绪,显示的还是第1帧。这种情况被Android开发组命名为“Jank”。
Step5. 当第2帧数据准备完成后,它并不会马上被显示,而是要等待下一个VSync。
所以总的来说,就是屏幕平白无故地多显示了一次第1帧。原因大家应该都看到了,就是CPU没有及时地开始着手处理第2帧的渲染工作,以致“延误军机”。
其实总结上面的这个情况之所以发生,首先的原因就在于第二帧没有及时的绘制。我们将在三重缓冲一节中再讲解这种情况)。那么如何使得第二帧即使被绘制呢?
这就是我们在Graphic系统中引入VSYNC的原因,考虑下面这张图:
如上图所示,一旦VSync出现后,立刻就开始执行下一帧的绘制工作。这样就可以大大降低Jank出现的概率。另外,VSYNC引入后,要求绘制也只能在收到VSYNC消息之后才能进行,因此,也就杜绝了另外一种极端情况的出现—-CPU(GPU)一直不停的进行绘制,帧的生成速度高于屏幕的刷新速度,导致生成的帧不能被显示,只能丢弃,这样就出现了丢帧的情况—-引入VSYNC后,绘制的速度就和屏幕刷新的速度保持一致了。
经过上面的介绍,希望读者对Jank 和VSYNC有所认识。下面将说明怎么来得到FPS和卡顿Jank帧数。
2 Jank 和 FPS
我们只关注present time。
2.1 计算Janky frames
这里的frame duration是有present time两两相减得到的。
由上图可以得到jank 帧,右下角。
2.2 FPS
帧率(FPS)由present time的最后一帧减去第一帧得到时间值,然后除以帧数得到。
3 自动化获取
自动化思路:使用python 结合uiautomator,根据配置信息,启动想评测的app,操作app(滑动,放大等等),打印surfaceflinger数据出来,稍微处理一下即可得到fps和掉帧数。
步骤:
(1)清理历史数据
○ adb shell dumpsys SurfaceFlinger --latency-clear <window name>
(2)使用uiautomator操作某个APP
○ fling, scroll, zoom
(3)根据2操作,打印数据
○ adb shell dumpsys SurfaceFlinger --latency <window name>
(4)处理数据
如读者会使用Python的话,直接按照上面几步即可得到FPS和Jank 数,因为逻辑已经很清晰了。本人写的代码较多,这里不附上说明。
相关文章推荐
- ASP.NET WebAPI 12 Action的执行
- Direct3D 2D文本绘制
- C#(WPF)按钮图片不显示,壁纸切换功能
- uva 437——The Tower of Babylon
- iPad开发之Split Views
- 图像拼接
- 递归排序
- Python学习笔记(11)
- html手机自适应屏幕
- 数据结构--红黑树(java)
- tomcat 多实例部署
- 1075. PAT Judge (25)
- 贪婪算法小结
- POJ 1195 Mobile phones 【二维树状数组】
- javaSE(02)
- 第二次spring冲刺第1天
- 1075. PAT Judge (25)
- 我遇到的错误提示:reason: '*** setObjectForKey: object cannot be nil (key: id)' 的病因
- 约瑟夫问题解决及实现代码(C语言版)
- Oracle体系结构总结