APP性能测试——卡顿、流畅度测试

APP性能测试——卡顿、流畅度测试一 先了解几个缩写的含义 fps 一秒内绘制到屏幕的帧数 通常 60hz 的手机 1s 是 60 帧 目前高端机基本 120hz jank 卡顿次数 bigJank 严重卡顿次数 stutter 卡顿率 卡顿时长 总时长 lostFrame 丢帧率 实际帧数 预期帧数

大家好,我是讯享网,很高兴认识大家。

一、先了解几个缩写的含义:

    • jank:卡顿次数
    • bigJank:严重卡顿次数
    • stutter:卡顿率=卡顿时长/总时长
    • lostFrame:丢帧率=实际帧数/预期帧数
    • frameInfo:帧耗时,即每一帧渲染耗
    fps:一秒内绘制到屏幕的帧数(通常60hz的手机1s是60帧,目前高端机基本120hz)

二、以 Google Vitals 的卡顿描述为准,即呈现速度缓慢和帧冻结两个维度判断:

    • 帧冻结:帧冻结的绘制耗时超过 700ms,为严重卡顿问题。
    • 卡顿忽略 FPS<=2 的页面:因为人的视觉暂留 100~400ms,即 FPS 在 2.5~10 之间时,所以当 FPS 低于 3 时,人眼看到的并不是连续动作,即使有丢帧现象,也不会察觉。
    • FPS和卡顿无任何关系:假如1s内,前800ms刷新了50帧,但是由于卡顿最后200ms刷新了1帧。这1s的帧率为51帧,从fps上来看51帧已经非常好了,但是用户在这1s内会感觉到一次明显的卡顿。
    呈现速度缓慢:在呈现速度缓慢的帧数较多的页面,当超过 50% 的帧呈现时间超过 16ms 毫秒时,用户感官明显卡顿。

三、Jank 计算方法:

      • 当前帧耗时>两帧电影帧耗时 (1000ms/24*2=84ms,低于24帧画面,人眼就能感知到画面不连续性)。
      当前帧耗时>前三帧平均耗时 2 倍(人眼一般可容忍2帧延迟)。
    • 严重卡顿 BigJank(同上):
      • 当前帧耗时>前三帧平均耗时 2 倍。
      • 当前帧耗时>三帧电影帧耗时 (1000ms/24*3=125ms)。
    普通卡顿 Jank(由于硬件的发展,现在中高端手机基本都是120hz,肉眼对于流畅度越来越敏感,实际测试中满足以下一条即可判断为卡顿)

四、卡顿标准:

    目前了解到某游戏大厂的卡顿率是5%以下,我们主要是app页面,所以我建议:

  •  卡顿不要高于10%,对于高级别项目要求不能超过5%
    • 当页面切换时,系统会产生一些超大帧,导致卡顿率上升,可以忽略
    • 中端机FPS不低于56

五、实际测试中需要关注的场景:

    • 只需关注FPS,理论PFS应该为0,否则,说明页面有冗余刷新,可能是bug,容易引起手机发热及耗电。
    • 有滚动动画页面窗口
      • 只需关注FPS,FPS处于合适值即可,无需高频刷新,一般fps20以上。
    • 快速滑动页面窗口(同"四"中的标准)
      • 需要关注FPS、卡顿率,手机交互灵敏度就是来源于此。
    • 播放视频、游戏页面窗口
      • 需要关注FPS、Jank及卡顿率,一般帧率20-24帧,卡顿率5%以下,目前高端机可以做到60-90帧。
    静态页面窗口

六、测试方法:

  • 工具类:perfdog、totorobox、Snapdragon Profiler 等
  • 脚本类:adb官方命令行,通过adb命令获取并计算卡顿率、丢帧率、FPS等指标,测试前需要在手机的开发者选项中,找到“GPU呈现模式分析”,选择“在adb shell dumpsys gfxinfo中”
    • 静止页面、banner滚动等通过工具做测试,不再赘述
    • 常规测试中我们更关注可快滑的长列表页面,以下主要针对快滑场景的流畅度测试

1、计算每次滑动时系统记录的数据:

# 使用系统命令获取帧率数据# 以下为示例代码:def get_fps(pkg_name, devices): #fps 测试 _adb = "adb -s " + devices +" shell dumpsys gfxinfo %s" % pkg_name    os.system("adb -s " + devices +" shell dumpsys SurfaceFlinger --latency-clear")        # 初始化数据,如fps、卡顿时间、丢帧率、卡顿率等    all_result={ 
  
    
   "jankFrames": 0, # jank次数,跳帧数        "totalFrames" :  0,  # 统计的总帧数        ... }    results = os.popen(_adb) flag=False every_frame_Time= [] # 每帧耗时  for line in results.readlines():        line=line.strip() if flag and line : times = line.split("\t") # 计算一帧所花费的时间 if len(times)>3: onceTime = float(times[0])+float(times[1])+float(times[2])+float(times[3]) every_frame_Time.append(onceTime) all_result['alltime']+=onceTime all_result['totalFrames'] += 1 # 统计总帧数 if onceTime > 16.67: # 以Android定义的60FPS为标准 all_result['test_alltime']+=onceTime                    all_result['jankFrames'] += 1# 统计跳帧jank数 all_result['vsyncOverTimes'] +=int(onceTime / 16.67) # 向下取整即可 else: all_result['test_alltime']+=16.67                    # 普通卡顿 Jank条件: if len(every_frame_Time)>=3: if onceTime>(every_frame_Time[-1]+every_frame_Time[-3]+every_frame_Time[-2])/3*2: all_result['jankTime']+=onceTime if all_result['totalFrames'] >0: all_result['fps'] = all_result['totalFrames'] / (all_result['totalFrames'] + all_result['vsyncOverTimes']) * 60 all_result['lostFrameRate'] = all_result['jankFrames'] / all_result['totalFrames'] ... # print("fps(1秒内平均画面刷新次数)值为:",fps)        # print("总帧数:",totalFrames) else: print("【ERROR】无FPS信息,请确认手机正常连接或APP正常运行")    return all_result

讯享网

2、计算滑动周期内的所有数据平均值:

讯享网# 以下为示例代码:def record_fps(sencens,t): global stop avg_all_reuslt= { 
  
    
   "jankFrames": 0, # jank次数,跳帧数 "totalFrames" : 0, # 统计的总帧数 ... } while True: if stop==0: all_result=get_fps(package, serialno) avg_all_reuslt['jankFrames']+=all_result['jankFrames'] avg_all_reuslt['totalFrames']+=all_result['totalFrames'] ... else: break    if  avg_all_reuslt['totalFrames'] >0: avg_all_reuslt['fps'] = round( avg_all_reuslt['totalFrames'] / (avg_all_reuslt['totalFrames'] + avg_all_reuslt['vsyncOverTimes']) * 60,4) avg_all_reuslt['lostFrameRate']=round( avg_all_reuslt['jankFrames'] / avg_all_reuslt['totalFrames'],4)        avg_all_reuslt['jankRate'] =round( avg_all_reuslt['jankTime'] / avg_all_reuslt['test_alltime'],4)         ... 记录每个场景的自动化值 if t==0: allJson_result[sencens]=[avg_all_reuslt,] else:            allJson_result[sencens].append(avg_all_reuslt)        # 数据入库示例代码        insert_mysql(devices,sencens.allJson_result)    stop = 0

示例:不同维度的聚合,能否反映出不同版、不同时间段的性能的数据,可进行版本数据监控,历史版本数据对比,示例:

七、总结:

    在实际测试当中,我们主要关注三个指标:FPS、卡顿率、丢帧率即可,通过这三个指标能够清晰地反映出当前app的体感现状,对于后期制定标准、促进优化效果、提高产品质量都会有一定的帮助;当然我们也可以根据可视化工具来辅助测试,来提升测试准确度,通过脚本能够弥补可视化工具的不足,脚本能够做成自动化,以节约测试时间和人力成本,提升效率。

*完整代码,关注公众号后,赞赏留言获取!

长按关注QuTest,定期分享技术干货,欢迎投稿!

小讯
上一篇 2025-03-29 18:47
下一篇 2025-02-17 15:03

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/64605.html