为什么requestiAnimationFrame如此波动和不一致? ubuntu上的chrome

时间:2017-09-28 20:18:05

标签: javascript google-chrome firefox requestanimationframe

这可能是在黑暗中拍摄的,但我不知道造成这种情况的原因。

我开发了一个带webgl的游戏引擎。我的主要测试浏览器是firefox,一切都很完美。没有滞后或随机的口吃,即使我做了更强烈的事情,比如混合多个帧缓冲区。

然而,在Chrome上,这是另一个故事。即使运行最简单的任务,Chrome也很难保持稳定的fps。我决定创建一个实验来查看问题是在我的代码中还是在requestAnimation循环中。这是我运行的代码:

<!DOCTYPE html>
<html>
<body>
<div id="fpsCounter"></div>

Lowest fps
<div id="minFps"></div>

<br>
Highest fps
<div id="maxFps"></div>
<script>
    var minFps = 999;
    var maxFps = 0

    var fps = 0;
    var last = performance.now();
    var now;
    var fpsUpdateTime = 20;
    var fpsUpdate = 0;
    var fpsCounter = document.getElementById("fpsCounter");
    var minFpsEle = document.getElementById("minFps");
    var maxFpsEle = document.getElementById("maxFps");
    function timestamp(){
        return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
    }


    var getMaxFps = false;
    setTimeout(function(){
        getMaxFps = true;
    }, 2000);

    function gameLoop(){
        now = performance.now();
        if(fpsUpdate == 0){
            fps = 1000 / (now - last);
            fpsUpdate = fpsUpdateTime;
        }
        fpsUpdate--;

        fpsCounter.innerHTML = fps;
        if(parseInt(fps, 10) < parseInt(minFps, 10)){
            minFps = parseInt(fps, 10);
            minFpsEle.innerHTML = minFps;
        }

        if(parseInt(fps, 10) > parseInt(maxFps, 10) && getMaxFps){
            maxFps = parseInt(fps, 10);
            maxFpsEle.innerHTML = maxFps;
        }

        last = now;
        requestAnimationFrame(gameLoop);
    }
    gameLoop();
</script>
</body>

</html>

所有代码都是循环动画帧并将fps放入div。在Firefox上,它的工作方式与整个游戏引擎一样,平均保持在58左右,从不低于52 fps。 Chrome挣扎于40 fps以上且频率低于28.奇怪的是,Chrome有一些频繁的速度爆发,最高fps chrome得到了99 fps,但这有点毫无意义,因为稳定的60 fps更重要。

详细说明:

Firefox version: 55.0.2 64-bit
Chrome version: 60.0.3112.78 (official version) 64-bit
OS: Ubuntu 16.04 LTS
Ram: 8gb
GPU: gtx 960m
Cpu: intel core i7HQ

这就是Chrome在性能方面的表现: enter image description here

1 个答案:

答案 0 :(得分:0)

我制作了这个简约的html页面进行测试:

<!DOCTYPE html>
<html>
<head>
    <title>requestAnimationFrame</title>
</head>
<body>
    <canvas id="canvas" width="300" height="300"></canvas>
    <script>
    "use strict"

    // (tested in Ubuntu 18.04 and Chrome 79.0)
    //
    // requestAnimationFrame is not precise
    // often SKIPs a frame
    //

    function loop() {
        requestAnimationFrame(loop)
        var ctx = document.getElementById("canvas").getContext("2d")
        ctx.fillStyle = "red"
        ctx.fillRect(100,100,200,100)
    }

    loop()
    </script>
</body>
</html>

summary - dev tools image

没有内存泄漏问题。 脚本执行时间可以忽略不计。

fps - dev tools image

FPS的行为不一致(在Ubuntu上运行Chrome)。

此测试中,问题出在硬件加速上。

禁用硬件加速后,FPS正常。


已编辑

我对仅包含一个画布的页面进行了更多测试。 我的结论是,浏览器过于复杂(或错误),几乎不可能100%地流畅运行。


我的游戏架构

var previousTimeStamp = 0

function mainLoop(timeStamp) {
    if (! shallSkipLoop(timeStamp)) { gameLoop() } 
    requestAnimationFrame(mainLoop)
}

function gameLoop() {    
    // some code here
}    

function shallSkipLoop(timeStamp) { 
    var deltaTime = timeStamp - previousTimeStamp
    previousTimeStamp = timeStamp
    //
    // avoiding bad frame without less than 1000 / 60 ms!!!
    // this happens when browser executes a frame too late 
    // and tries to be on time for the next screen refresh;
    // but then may start a long sequence of unsynced frames:
    // one very short (like 5ms) the other very long (like 120ms)
    // maybe it is a bug in browser
    //
    return deltaTime < 16
}

requestAnimationFrame(mainLoop)