Javascript 检查JS中的FPS?

Javascript 检查JS中的FPS?,javascript,html,canvas,Javascript,Html,Canvas,如何检查javascript的fps?我用这个循环: gameloopId = setInterval(gameLoop, 10); 在gameLoop中,查看new Date和new Date与上一个循环之间的差异(将其存储在变量中)。 换言之: var lastLoop = new Date(); function gameLoop() { var thisLoop = new Date(); var fps = 1000 / (thisLoop - lastLoop);

如何检查javascript的fps?我用这个循环:

gameloopId = setInterval(gameLoop, 10);

gameLoop
中,查看
new Date
new Date
与上一个循环之间的差异(将其存储在变量中)。
换言之:

var lastLoop = new Date();
function gameLoop() { 
    var thisLoop = new Date();
    var fps = 1000 / (thisLoop - lastLoop);
    lastLoop = thisLoop;
    ...
}

thisLoop-lastLoop
是两个循环之间经过的毫秒数。

由@Slaks编写的代码只提供最后一帧的瞬时FPS,可能会因打嗝而变化或产生误导。我更喜欢使用易于编写和计算的低通滤波器来消除快速瞬变,并显示最近结果的合理伪平均值:

// The higher this value, the less the fps will reflect temporary variations
// A value of 1 will only keep the last value
var filterStrength = 20;
var frameTime = 0, lastLoop = new Date, thisLoop;

function gameLoop(){
  // ...
  var thisFrameTime = (thisLoop=new Date) - lastLoop;
  frameTime+= (thisFrameTime - frameTime) / filterStrength;
  lastLoop = thisLoop;
}

// Report the fps only every second, to only lightly affect measurements
var fpsOut = document.getElementById('fps');
setInterval(function(){
  fpsOut.innerHTML = (1000/frameTime).toFixed(1) + " fps";
},1000);
此过滤器的“半衰期”从旧值移动一半到新的稳定值所需的帧数为
filterStrength*Math.log(2)
(大约为强度的70%)

例如,
20
的强度将在14帧中移动到瞬时变化的一半,在28帧中移动到瞬时变化的3/4,在46帧中移动到瞬时变化的90%,在92帧中移动到瞬时变化的99%。对于以大约30fps的速度运行的系统,性能的突然、剧烈变化在半秒钟内会很明显,但仍然会“丢弃”单帧异常,因为它们只会将值移动5%的差值

这里是一个不同的过滤器强度的视觉比较,一个30帧的游戏,有一个瞬间下降到10帧,然后再加速到50帧。如您所见,较低的过滤器值可以更快地反映“良好”的更改,但也更容易出现暂时的问题:


最后,这里是使用上述代码对“游戏”循环进行实际基准测试的示例。

我使用它来计算fps

  var GameCanvas = document.getElementById("gameCanvas");
  var GameContext = doContext(GameCanvas,"GameCanvas");
  var FPS = 0;
  var TimeNow;
  var TimeTaken;
  var ASecond = 1000;
  var FPSLimit = 25;
  var StartTime = Date.now();
  var TimeBefore = StartTime;
  var FrameTime = ASecond/FPSLimit;
  var State = { Title:0, Started:1, Paused:2, Over:3 };
  var GameState = State.Title;

  function gameLoop() {
    requestAnimationFrame(gameLoop);
    TimeNow = Date.now();
    TimeTaken = TimeNow - TimeBefore;

    if (TimeTaken >= FrameTime) {
      FPS++
      if((TimeNow - StartTime) >= ASecond){
        StartTime += ASecond;
        doFPS();
        FPS = 0;
      }

      switch(GameState){
        case State.Title :
          break;
        case State.Started :
          break;
        case State.Paused :
          break;
        case State.Over :
          break;
      }
      TimeBefore = TimeNow - (TimeTaken % FrameTime);
    }
  }

  Sprites.onload = function(){
    requestAnimationFrame(gameLoop);
  }

  function drawText(Context,_Color, _X, _Y, _Text, _Size){
    Context.font =  "italic "+ _Size +" bold";
    Context.fillStyle = _Color;
    Context.fillText(_Text, _X, _Y);
  }

  function doFPS()(
    drawText(GameContext,"black",10,24,"FPS : " + FPS,"24px");
  }

  function doContext(Canvas,Name){
    if (Canvas.getContext) {
      var Context = Canvas.getContext('2d');
      return Context;
    }else{
      alert( Name + ' not supported your Browser needs updating');
    }
  }
那怎么办

我的2美分:

比较优化对我很有用。 当然,只为测试消耗一点资源

理想情况下,当使用事件、循环等时,在完全使用的情况下,应用程序帧速率应始终保持在每帧50毫秒以下。这等于20帧每秒

人眼感觉滞后低于24 FPS,这是1000/24=41ms

因此,41ms对于一帧来说是保持自然流动性的最小时间窗口。要避免高于这个数字

let be=Date.now(),fps=0;
请求动画帧(
函数循环(){
让现在=Date.now()
fps=数学四舍五入(1000/(现在为be))
现在
requestAnimationFrame(循环)
如果(fps<35){
kFps.style.color=“红色”
kFps.textContent=fps

}如果(fps>=35&&fps非常好的图形!你是怎么做到的?@BennyNeugebauer上述内容是在Excel中创建的,只是因为它比一次创建要简单一些。是否有任何原因使我在使用请求动画帧时获得无限fps。我使用过滤器强度1来获得最精确的fps?这种情况时有发生(无限fps):@CezarisLT Infinite fps==一个回调报告与上一个调用相同的时间(
new Date
)。您可以通过bailing
if(thisLoop==lastLoop)对此进行保护
。但是,请注意,如果您使用的过滤器强度为
1
,则使用过滤器毫无意义。只需使用@SLaks-answer即可。@Phrogz我知道我参加聚会有点晚了。。但即使我使用您建议的防护措施来防止无限fps错误。我仍然会得到无限fps?有任何建议吗?您可以按日期替换新日期。现在(),同样的事情,但更正确的是,如何根据实际fps刷新函数gameLoop()?因为在使用setInterval()时,我只能传递时间间隔的参数一次。@JacekDziurdzikowski:Call
setTimeout()
每次安排下一帧。@JacekDziurdzikowski使用
requestAnimationFrame
比使用
setInterval()
setTimeout()
的性能更好,因为它会自动调整fps的计时。
var before,now,fps;
before=Date.now();
fps=0;
requestAnimationFrame(
    function loop(){
        now=Date.now();
        fps=Math.round(1000/(now-before));
        before=now;
        requestAnimationFrame(loop);
        console.log("fps",fps)
    }
 );