美文网首页
界面FPS流畅度(卡顿值)评估公式

界面FPS流畅度(卡顿值)评估公式

作者: 泗水亭长matthew | 来源:发表于2022-11-27 08:55 被阅读0次

    界面fps能达到60 且每帧间隔在16.7ms左右,用户流畅度体感为最高。出现掉帧(帧速减少), 抖帧(帧速不均匀),则认为会影响到用户流畅度体验。目前

    百度

    开发同学提供了可以设置一段时间内帧长的Demo,经过产品同学多轮、多人的试验结论:

    连续5帧帧长为30ms时,能够在网页浏览的界面滑动时明确感觉到抖动。

    单帧帧长为70ms时,能够在网页浏览的界面滑动时明确感觉到界面顿住。

    腾讯

    PerfDog Jank计算方法:

    1.      同时满足以下两条件,则认为是一次卡顿Jank.

    a)      当前帧耗时>前三帧平均耗时2倍。

    b)      当前帧耗时>两帧电影帧耗时(1000ms/24*2=84ms)。

    2.      同时满足两条件,则认为是一次严重卡顿BigJank.

    a)      当前帧耗时>前三帧平均耗时2倍。

    b)      当前帧耗时>三帧电影帧耗时(1000ms/24*3=125ms)。

    1)      BigJank:1s内严重卡顿次数

    2)      Jank(/10min):平均每10分钟卡顿次数。

    3)      BigJank(/10min):平均每10分钟严重卡顿次数

    目前市面上有些做卡顿评估的方案,但是计算方法取值太过离散,不具备连续性。我们需要一个能评测当前帧率的公式,计算出每帧的评分。来对界面流畅度有个完善的评估。

    几个重要指标

    1.平均帧率 (平均帧率不能检测出短时间内突然卡顿后又恢复的情况)

    2.帧率方差 (方差只能检测帧速的波动,如果帧速一直是30,方差也会为0)

    3.掉帧卡顿比率  (若某帧时长超过了30ms 则认为丢失了一帧)

    4.降帧次数 (平均每秒相邻两个FPS点下降大于8帧的次数)

    5. Ft 当前帧耗时

    FS = FrameSpeed = 16.7/Ft : 手机满帧率是一秒60帧,平均每帧16.7ms, 假定满帧速=16.7/16.7 = 1 , 当前帧耗时越多,速度越慢,最低趋近于0. 故帧速取值区间为(0, 1]

    由于用户感知卡顿与帧速和帧速波动值有关, 所以计算流畅值的公式应该与用户当前帧速,与帧速的导数dx相关, 由于导数的取值范围为(-∞, +∞), 因此我们使用上下两帧帧速差值的平方来评估速率波动,整体公式为: 其中 为当前帧帧速FS。

    如果当前帧为连续的第四帧满帧速(遇到连续的4帧,帧速为1)则把当前帧流畅值恢复为100

    式中 a=4  b=1 t = 0.85  t=>(0,1]

    公式说明:

    其中a 为当前帧速的权重值,  b为当前帧与上一帧速波动的权重值

    由于:

    使用试验数据

    [16.7, 16.7, 32, 32, 32, 32, 32, 16.7, 16.7, 70, 170, 170, 170, 170, 16.7, 16.7, 16.7, 16.7, 120, 16.7]

    当a=1 b=1 时计算出流畅值为

    [100, 100, 64, 58, 55, 53, 52, 65, 82, 24, 16, 12, 11, 10, 14, 57, 78, 89, 14, 20]

    当a=2 b=1 时流畅值为

    [100, 100, 60, 54, 53, 52, 52, 76, 92, 27, 14, 11, 10, 10, 42, 80, 93, 97, 17, 47]

    当a=3 b=1 时流畅值为

    [100, 100, 58, 53, 52, 52, 52, 82, 95, 27, 13, 10, 10, 9, 57, 89, 97, 99, 16, 60]

    [100.0, 100.0, 61.3, 61.3, 60.2, 58.1, 57.9, 87.1, 91.5, 32.1, 16.7, 18.0, 15.5, 14.4, 66.9, 79.2, 88.9, 95.6, 17.6, 91.8]

    import os, sys, math

    import queue, random

    import matplotlib.pyplot as plt

    import numpy as np

    class SmoothAlgrithm:

        frameFullTime = 1000/60

        speedQueue = [1.0, 1.0, 1.0]

        smoothQueue = [1.0, 1.0, 1.0]

        smoothLayout = {}

        totalSmooth = 0

        duration = 0

        calDuration = 0

        frameCount = 0

        originSmoothArr = []

        curSmoothArr = []

    def __init__(self):

    self.smoothLayout = {'A':0, 'B':0, 'C':0, 'D':0, 'E':0}

    def getFrameSmooth(self, frameTime):

    self.duration += frameTime

    if (frameTime < self.frameFullTime):

                frameTime = self.frameFullTime

    self.calDuration += frameTime

            speed = self.frameFullTime / frameTime

            avgSpeed = sum(self.speedQueue) / len(self.speedQueue)

            avgSmooth = sum(self.smoothQueue) / len(self.smoothQueue)

    if (avgSpeed == 1.0 and speed == 1.0):

                score = 1

                smooth = 100

    else:

                score = (4*math.pow(speed, 0.90) - pow((speed - avgSpeed), 2) + avgSmooth) / 5

                smooth = (score*100)

    self.speedQueue.insert(0, speed)

    del self.speedQueue[-1]

    self.smoothQueue.insert(0, score)

    del self.smoothQueue[-1]

    if (smooth > 80):

    self.smoothLayout['A'] =  self.smoothLayout['A'] + 1

    elif (smooth > 60):

    self.smoothLayout['B'] =  self.smoothLayout['B'] + 1

    elif (smooth > 40):

    self.smoothLayout['C'] =  self.smoothLayout['C'] + 1

    elif (smooth > 20):

    self.smoothLayout['D'] =  self.smoothLayout['D'] + 1

    else:

    self.smoothLayout['E'] =  self.smoothLayout['E'] + 1

    self.frameCount += 1

    self.originSmoothArr.append(int(smooth))

    self.totalSmooth += smooth / speed

    self.curSmoothArr.append(int(smooth / speed))

    return smooth

    def setFrameArr(self, arr):

            smooths = []

    for ft in arr:

                smooth = int(self.getFrameSmooth(ft)*10)/10

                smooths.append(smooth)

    print(smooths)

    def calAvgSmooth(self):

            frameNumber = self.duration / self.frameFullTime

    print('Origin smooth:', int(sum(self.originSmoothArr)/self.frameCount))

    print('cur smooth:', int(sum(self.curSmoothArr)/frameNumber))

            calFrames = self.calDuration / self.frameFullTime

    print('cal smooth:', int(sum(self.curSmoothArr)/calFrames))

    def calFPS(self):

    print('cur fps:', int(self.frameCount*1000/self.duration))

    maxFrameTime = 200

    def randomFrametime():

        rdnum = random.randint(0, 100)

    if (rdnum < 90): #70%的满帧

    return 16;

        rdnum = random.randint(0, 350) #20% 16.7-35

    if (rdnum > 167):

    return rdnum / 10.0

        rdnum = random.randint(350, maxFrameTime*10) / 10.0 #10 分布在35-200

    return rdnum

    def randPrduceSmooth():

        smoothAlg = SmoothAlgrithm()

        ftSmoothTuple = [(0,0, []) for x in range(0, maxFrameTime+1)]

    for i in range (0, maxFrameTime*1000):

            ft = randomFrametime()

            smooth = smoothAlg.getFrameSmooth(ft)

            idx = int(ft)

            ftSmoothTuple[idx][-1].append(smooth)

    for idx in range(16, maxFrameTime+1):

            ftSmooth = ftSmoothTuple[idx]

            count = len(ftSmooth[-1]) or 1

            avgFtSmooth = sum(ftSmooth[-1]) / count

            avgFtSmooth = int(avgFtSmooth*10)/10.0

            ftSmoothTuple[idx] = (avgFtSmooth, count, ftSmooth[-1])

    print((idx, count, avgFtSmooth))

        x = np.arange(16,maxFrameTime)

        y = [ftSmoothTuple[idx][0] for idx in range(16,maxFrameTime)]

        plt.plot(x,y,"ob")

        plt.ylabel('smooth')

        plt.xlabel('frametime')

        plt.show()

    smoothAlg = SmoothAlgrithm()

    #arr = [2, 11.0, 13.4, 16.7, 32, 32, 32, 32, 32, 16.7, 16.7, 70, 170, 170, 170, 170, 16.7, 16.7, 16.7, 16.7, 120, 16.7]

    arr = [1 for x in range(0, 60)]

    smoothAlg.setFrameArr(arr)

    print("framecount: ", len(arr),  "framenumber:",  int(sum(arr)/smoothAlg.frameFullTime), "  duration:", sum(arr))

    print("\n orignarr:", smoothAlg.originSmoothArr)

    print("\n curarr:", smoothAlg.curSmoothArr)

    smoothAlg.calFPS()

    smoothAlg.calAvgSmooth()

    相关文章

      网友评论

          本文标题:界面FPS流畅度(卡顿值)评估公式

          本文链接:https://www.haomeiwen.com/subject/txmhfdtx.html