web-dev-qa-db-ja.com

JSでFPSを確認しますか?

Javascriptのfpsを確認するにはどうすればよいですか?私はこれを使用してループしています:

gameloopId = setInterval(gameLoop, 10);
34
CyanPrime

gameLoopで、new Dateおよびnew Date最後のループから(変数に格納します)。
言い換えると:

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

thisLoop - lastLoopは、2つのループ間で経過したミリ秒数です。

25
SLaks

@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%、99%で変化します。 92フレーム。約30 fpsで実行されているシステムの場合、パフォーマンスの急激な急激な変化は0.5秒で明らかになりますが、単一フレームの異常は「差」の5%だけシフトするため、「破棄」されます。

以下は、10fpsに瞬間的に低下し、その後最大50fpsに達する〜30fpsゲームのさまざまなフィルター強度の視覚的な比較です。ご覧のとおり、フィルター値を低くすると、「良い」変更がより迅速に反映されますが、一時的なしゃっくりの影響も受けやすくなります。
enter image description here

最後に、 上記のコードを使用して実際に「ゲーム」ループのベンチマークを行います。

93
Phrogz

requestAnimationFrame についてはどうですか?

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)
    }
 );
2
davidmars

これを使用して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
sha1962

私の2セント:

最適化を比較するのに役立ちます。もちろん、テストのためだけにリソースを少し燃やします。

理想的には、アプリのフレームレートは、イベント、ループなどを使用する場合、フル使用時に、秒単位で50フレームを超えないようにする必要があります。

とにかく、少なくとも現時点では、画面が60hzを超えると更新されません。

人間は24 FPS未満のラグを感じます。これは1000/24 = 41ms

したがって、フレームの41ミリ秒は、感情がフリーズする前の最後の重要な最低ポイントです。

let be = Date.now(),fps=0;
requestAnimationFrame(
    function loop(){
        let now = Date.now()
        fps = Math.round(1000 / (now - be))
        be = now
        requestAnimationFrame(loop)
        if (fps < 35){
          kFps.style.color = "red"
          kFps.textContent = fps 
        } if (fps >= 35 && fps <= 41) {
            kFps.style.color = "deepskyblue"
            kFps.textContent = fps + " FPS"
          } else {
            kFps.style.color = "black"
            kFps.textContent = fps + " FPS"
        }
        kpFps.value = fps
    }
 )
<span id="kFps"></span>
<progress id="kpFps" value="0" min="0" max="100" style="vertical-align:middle"></progress>

アイデアを得るためのループである50ミリ秒間隔がスムーズに維持されるはずです!進行状況バーのジャンプを確認しますか?これはフレーム損失であり、ブラウザは次のフレームにジャンプすることで犠牲を払おうとしますが、それを避ける必要があります!

let t
for (let i=0;i<99999;i++){
  t = setTimeout(function(){
   console.log("I am burning your CPU! " + i)
   clearTimeout(t)
  },50)
  
}
0
NVRM