移动性能测试 Android FPS 方法探讨

花开 · October 25, 2019 · Last by 浮云 replied at October 29, 2019 · 1135 hits

最近在学习Android稳定性测试相关的知识点,目前主要参考xinxi 的 持续集成中的 Android 稳定性测试, 但是在看到FPS相关指标的数据的时候,我发现了一些不一样的地方,然后发现社区多数的计算方法都是来自这一篇文章 FPS 计算方法的比较, 然后我就产生了疑问?我的数据是这样的:

环境

  • 木木摸机器
  • 系统6.0
  • 测试app 雪球
Applications Graphics Acceleration Info:
Uptime: 17498916 Realtime: 17498916

** Graphics info for pid 1306 [com.xueqiu.android] **

Stats since: 1014402977980ns
Total frames rendered: 15148
Janky frames: 4108 (27.12%)
90th percentile: 18ms
95th percentile: 22ms
99th percentile: 44ms
Number Missed Vsync: 215
Number High input latency: 9
Number Slow UI thread: 634
Number Slow bitmap uploads: 27
Number Slow issue draw commands: 3106

Caches:
Current memory usage / total memory usage (bytes):
TextureCache 23542452 / 25165824
LayerCache 32768 / 16777216 (numLayers = 1)
Layer size 128x64; isTextureLayer()=0; texid=943 fbo=0; refs=1
Layers total 32768 (numLayers = 1)
RenderBufferCache 0 / 2097152
GradientCache 16384 / 524288
PathCache 198843 / 4194304
TessellationCache 266880 / 1048576
TextDropShadowCache 0 / 2097152
PatchCache 4032 / 131072
FontRenderer 0 A8 1048576 / 1048576

FontRenderer 0 RGBA 0 / 0
FontRenderer 0 total 1048576 / 1048576
Other:

FboCache 0 / 0
Total memory usage:
25109935 bytes, 23.95 MB
Profile data in ms:
com.xueqiu.android/com.xueqiu.android.common.MainActivity/android.view.ViewRootImpl@9e9e9b8 (visibility=0)
Draw Prepare Process Execute
11.53 0.46 4.68 2.23
3.96 0.26 4.53 9.07
4.08 0.63 4.67 8.99
3.45 0.48 2.48 11.92
3.62 0.52 3.48 9.18
5.41 0.83 4.04 3.37
2.43 0.22 2.88 2.62
2.14 0.26 2.80 2.04
2.15 0.36 4.85 2.27
3.25 0.32 3.29 2.02
3.05 0.33 3.95 2.07
2.24 0.22 8.27 3.37
2.62 0.27 7.20 3.09
1.52 0.19 3.27 1.34
2.65 0.17 6.58 1.32
2.60 0.12 2.71 4.74
1.43 0.17 3.08 1.15
2.32 0.26 2.66 1.76
5.19 0.16 2.59 1.61


Stats since: 1014402977980ns
Total frames rendered: 15148
Janky frames: 4108 (27.12%)
90th percentile: 18ms
95th percentile: 22ms
99th percentile: 44ms
Number Missed Vsync: 215
Number High input latency: 9
Number Slow UI thread: 634
Number Slow bitmap uploads: 27
Number Slow issue draw commands: 3106
View hierarchy:

com.xueqiu.android/com.xueqiu.android.common.MainActivity/android.view.ViewRootImpl@9e9e9b8

629 views, 586.51 kB of display lists


Total ViewRootImpl: 1

Total Views: 629

Total DisplayList: 586.51 kB

测试代码如下:

cmd = "adb  shell dumpsys gfxinfo %s" % ('com.xueqiu.android')
result = os.popen(cmd).read().strip()
frames = [x for x in result.split('\n') if validator(x)]
for frame in frames:
time_block = re.split(r'\s+', frame.strip())

if len(time_block) == 3:
print (time_block)

结果

['Applications', 'Graphics', 'Acceleration', 'Info:']
['Uptime:', '17838571', 'Realtime:', '17838571']
['Total', 'frames', 'rendered:', '15951']
['Janky', 'frames:', '4375', '(27.43%)']
['Number', 'Missed', 'Vsync:', '216']
['TextureCache', '23546664', '/', '25165824']
['RenderBufferCache', '0', '/', '2097152']
['GradientCache', '16384', '/', '524288']
['PathCache', '198843', '/', '4194304']
['TessellationCache', '266880', '/', '1048576']
['TextDropShadowCache', '0', '/', '2097152']
['PatchCache', '4032', '/', '131072']
['FboCache', '0', '/', '0']
['25114147', 'bytes,', '23.95', 'MB']
['Profile', 'data', 'in', 'ms:']
['Draw', 'Prepare', 'Process', 'Execute']
['13.13', '0.54', '5.32', '2.91']
['4.10', '0.26', '4.73', '7.49']
['4.51', '1.13', '5.86', '6.09']
['3.01', '0.51', '3.24', '10.94']
['2.37', '1.42', '4.53', '8.74']
['1.78', '0.54', '4.79', '10.27']
['1.93', '0.78', '2.76', '12.70']
['2.52', '0.28', '2.43', '12.89']
['2.03', '0.57', '2.37', '13.17']
['2.10', '0.26', '2.37', '12.42']
['1.83', '0.47', '2.76', '12.40']
['1.42', '0.46', '2.90', '12.35']
['1.19', '0.25', '2.83', '12.86']
['1.32', '0.40', '1.92', '13.32']
['4.32', '0.68', '2.16', '10.04']
['16.73', '0.63', '4.38', '4.26']
['4.80', '0.38', '4.32', '4.00']
['3.37', '0.45', '4.69', '8.29']
['2.60', '0.53', '8.96', '5.25']
['2.90', '1.98', '7.99', '5.82']
['2.84', '0.46', '5.11', '8.96']
['1.54', '0.62', '3.27', '12.16']
['1.91', '0.29', '3.20', '12.85']
['2.60', '0.36', '4.50', '9.75']
['1.69', '1.24', '3.32', '11.90']
['2.17', '0.50', '2.28', '13.18']
['2.34', '0.37', '3.42', '11.96']

问题

  • 目前输出数据是4列,所以这段代码是无效的,获取不到fps数据
  • 修改判断条件为 if len(time_block) == 4:, 出现很多无效的数据,虽然可以通过try,catch捕获,但是正常数据里面有了脏数据,这些数据计算结果应该是60fps

修复

通过正则获取目标数据

cmd = "adb  shell dumpsys gfxinfo %s" % ('com.xueqiu.android')
result = os.popen(cmd).read().strip()
data = re.findall(r'(?<=Execute)([\w\W]+)(?=Stats)', result)
frames = [x for x in data[0].split('\n') if validator(x)]
for frame in frames:
time_block = re.split(r'\s+', frame.strip())

if len(time_block) == 4:
print (time_block)

待解决问题

  • 通过返回数据判断出是三列还是四列,这个我相信大家都是可以做到的

这个是我觉得挺好的,分享一下

最佳回复

根据我的实际经验来看,FPS的数值其实意义不大,反而是janky rate的意义大于FPS。

直接以dumpsys gfxinfo命令获取的jankey rate数值来评价app的流畅度吧。

就先用最简单的FPS为例,用它来评估流畅度就有问题,例如用户掉了6帧,将近100ms,用户是能感受到卡顿的,但是FPS却是54FPS,这是个相当好的分数,在WWDC里面都赞的分数。因此应该用janky,也就是掉帧本身来定制指标,才能反映用户的卡顿。

具体可以参考这篇文章:https://www.jianshu.com/p/56775aa366cb

FPS只是数据,最终是要筛出问题提供给研发解决,这里的问题就是度量数据如何用?单从实现fps度量的方案上:
16年我设计了(https://testerhome.com/topics/4775)
今年又设计了(https://testerhome.com/topics/21045)
可实际问题上是用它们如何去解决问题,能解决什么问题?

1)要将需要研发解决的问题聚焦在什么程度线上?这就需要了解一般用户的体验需求
a、人眼有100ms延迟,一些人经过训练或长期适应高帧率场景会有卡顿敏感度提升
b、竞速类游戏有限制30帧的做法,核心是人眼对变化感知明显,所以有些场景控制帧率稳定比提高帧率有效果
c、视频及体验是从24帧电影录制及网络流视频25帧视频来的
d、20帧体验,作为一般帧率影响体验的游戏,20帧就是个底线了,就像ui上的gif动画一般是20帧播放,至少这是被人接受的

2)要和配合优化的研发达成一致的优化目标,要不实际会浪费在优化意义的争论上

3)说说我的经验中,用我自己的方案解决了哪些实际问题
a、手机rom游戏效果优化,目标:让游戏帧率稳定,通过策略调整看帧率波动。实际优化是温升限频策略、续航、游戏性能间找平衡点,带着目标做事才能有的放矢。
b、TV项目costdown,低端芯片mstar 648 1.5G内存项目,我给的目标,内存要给前台app提供至少500M可用内存,最终通过bsp、rom、系统app各层面的努力,配合后台查杀策略提供了800M左右可用内存;而帧率上通过单帧绘制jank比例发现SurfaceFlinger绘制性能有问题,结果通过研发优化思路探索,打开Gop的overlap实现减少一次io复制,使SurfaceFlinger绘制性能明显改善。
c、通过16年的方案分场景检查静止画面下,SurfaceFlinger的无实际意义绘制,控制了重复绘制图层、不关闭未在显示中的gif动画绘制两大类不合理性能开销的问题
d、基于流畅度评价,70分以上每10分跨度都可以感受到体验区别,从而把桌面插件上线标准控制在70分以上,目标80分以上的标准,有效把控了插件上线的流畅度体验。

基于这些应该能理解吧,不在于如何把数据拿到,最核心的是如何用。我扩展的抓取方式只是为了提供拿到数据的手段。

共收到 8 条回复 时间 点赞

之前测试FPS的时候,参考了 @sandman 的这篇文章:https://testerhome.com/topics/4775
我个人评估了一下,觉得这个比较准确

我记得我以前的方式是修改 Choreographer 的一个成员变量 xxx_LIMIT,本来默认是30,改成1,然后log就会输出所有的丢帧数据,再根据时间戳,计算同一秒内的丢帧

simple 回复

嗯,这个我也看了,昨天太晚了就没有尝试

CY 回复

我回头看看源代码,这样就需要修改代码了吧?还是我可以启动另一个程序来做这个操作的?

根据我的实际经验来看,FPS的数值其实意义不大,反而是janky rate的意义大于FPS。

直接以dumpsys gfxinfo命令获取的jankey rate数值来评价app的流畅度吧。

就先用最简单的FPS为例,用它来评估流畅度就有问题,例如用户掉了6帧,将近100ms,用户是能感受到卡顿的,但是FPS却是54FPS,这是个相当好的分数,在WWDC里面都赞的分数。因此应该用janky,也就是掉帧本身来定制指标,才能反映用户的卡顿。

具体可以参考这篇文章:https://www.jianshu.com/p/56775aa366cb

Joo 回复

学习了👍

FPS只是数据,最终是要筛出问题提供给研发解决,这里的问题就是度量数据如何用?单从实现fps度量的方案上:
16年我设计了(https://testerhome.com/topics/4775)
今年又设计了(https://testerhome.com/topics/21045)
可实际问题上是用它们如何去解决问题,能解决什么问题?

1)要将需要研发解决的问题聚焦在什么程度线上?这就需要了解一般用户的体验需求
a、人眼有100ms延迟,一些人经过训练或长期适应高帧率场景会有卡顿敏感度提升
b、竞速类游戏有限制30帧的做法,核心是人眼对变化感知明显,所以有些场景控制帧率稳定比提高帧率有效果
c、视频及体验是从24帧电影录制及网络流视频25帧视频来的
d、20帧体验,作为一般帧率影响体验的游戏,20帧就是个底线了,就像ui上的gif动画一般是20帧播放,至少这是被人接受的

2)要和配合优化的研发达成一致的优化目标,要不实际会浪费在优化意义的争论上

3)说说我的经验中,用我自己的方案解决了哪些实际问题
a、手机rom游戏效果优化,目标:让游戏帧率稳定,通过策略调整看帧率波动。实际优化是温升限频策略、续航、游戏性能间找平衡点,带着目标做事才能有的放矢。
b、TV项目costdown,低端芯片mstar 648 1.5G内存项目,我给的目标,内存要给前台app提供至少500M可用内存,最终通过bsp、rom、系统app各层面的努力,配合后台查杀策略提供了800M左右可用内存;而帧率上通过单帧绘制jank比例发现SurfaceFlinger绘制性能有问题,结果通过研发优化思路探索,打开Gop的overlap实现减少一次io复制,使SurfaceFlinger绘制性能明显改善。
c、通过16年的方案分场景检查静止画面下,SurfaceFlinger的无实际意义绘制,控制了重复绘制图层、不关闭未在显示中的gif动画绘制两大类不合理性能开销的问题
d、基于流畅度评价,70分以上每10分跨度都可以感受到体验区别,从而把桌面插件上线标准控制在70分以上,目标80分以上的标准,有效把控了插件上线的流畅度体验。

基于这些应该能理解吧,不在于如何把数据拿到,最核心的是如何用。我扩展的抓取方式只是为了提供拿到数据的手段。

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up