web-dev-qa-db-ja.com

HTML5Canvasのパフォーマンス-1秒あたりのループ/フレームの計算

以前、次のようないくつかの質問があったことを知っています。 JSでFPSを確認しますか? -ある程度は機能しましたが、各ループが完了するまでにかかった時間を知ることができました。 。

私が探しているのは、もっと読みやすく、制御しやすいものです。 FPSカウンターのリフレッシュレートを遅く設定して、人間が読める形式にするか、アプリケーションを実行できる速度で実行できるようにしたいので、ある種の速度計で使用できます。

とにかく、これが私が今持っているコードです:

var lastLoop = new Date().getTime();

function updateStage()
{   
    clearCanvas();
    updateStageObjects();
    drawStageObjects();     

    var thisLoop = new Date().getTime(); 
    var fps = (thisLoop - lastLoop);

    $('#details').html(fps);

    lastLoop = thisLoop;
    iteration = setTimeout(updateStage, 1);
}
  1. SetTimeout関数を1ミリ秒の速度に設定するのは正しいですか?これにより、ループができるだけ速くなると思っていました。

  2. 100フレームごとに数える必要があります。100フレームを実行するのに何ミリ秒かかったかを調べてから、ミリ秒が1000だった場合に何フレーム実行したかを計算しますか?この計算は何でしょうか?

  3. 結果をより正確にするために、1つのフレームが大幅に変化する可能性があるため、平均を表示する必要があると思いますが、これをどのように行う必要がありますか?

ヒントは大歓迎です。

ありがとう。

14
Henryz
  1. 出力の更新が速いほど、測定に影響を与えることに注意してください。最小限ですが、高速化する必要がない限り、fps出力を1秒に1回以下で更新しようとしています。

  2. 一時的な一時的な中断が値にあまり強く影響しないように、結果にローパスフィルターを設定するのが好きです。これは移動平均よりも計算と書き込みが簡単であり、「現在の」読み取り値が実行全体の合計パフォーマンスの影響を受ける全体的な平均の問題はありません(たとえば、起動時の異常な読み取り値)。

まとめると、私が通常FPSを測定する方法は次のとおりです。

var fps = 0, now, lastUpdate = (new Date)*1;

// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;

function drawFrame(){
  // ... draw the frame ...

  var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
  if (now!=lastUpdate){
    fps += (thisFrameFPS - fps) / fpsFilter;
    lastUpdate = now;
  }

  setTimeout( drawFrame, 1 );
}

var fpsOut = document.getElementById('fps');
setInterval(function(){
  fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000); 
23
Phrogz

私は何かを試しました、

変更した場合

lastUpdate = now

lastUpdate = now * 1 - 1;

NaNの問題は解決しました!これは、lastUpdateが定義されている場合にも使用されます。おそらく、日付をUNIXタイムスタンプに変換できないためです。

新しい結果は次のようになります。

var fps = 0, now, lastUpdate = (new Date)*1 - 1;

// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;

function drawFrame(){
  // ... draw the frame ...

  var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
  fps += (thisFrameFPS - fps) / fpsFilter;
  lastUpdate = now * 1 - 1;

  setTimeout( drawFrame, 1 );
}

var fpsOut = document.getElementById('fps');
setInterval(function(){
  fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000); 
3
Niels

投稿されたソリューションを採用し、少し強化しました。こちらをご覧ください- http://jsfiddle.net/ync3S/

  1. 毎回新しい日付オブジェクトを作成して参照しようとする代わりに、Date.now()を使用して、そのNaNエラーを修正しました。これにより、ガベージコレクションの必要性も防止されます。
  2. 変数名と関数名を少し整理し、コメントを追加しました。必須ではありませんが、用意しておくと便利です。
  3. テスト用の描画コードをいくつか含めました。
  4. エンジンループのテスト変数としてfpsDesiredを追加しました。
  5. 私はfpsDesiredでfpsAverageを開始したので、fpsFilterを使用すると、0から実際のFPSまでは機能せず、目的のFPSから開始し、そこから調整します。
  6. 描画は、すでに描画されている場合にブロックされるようになりました。これは、一時停止やその他の制御機能に使用できます。

メインブロックは次のとおりです。

var fpsFilter = 1; // the low pass filter to apply to the FPS average
var fpsDesired = 25; // your desired FPS, also works as a max
var fpsAverage = fpsDesired;
var timeCurrent, timeLast = Date.now();
var drawing = false;

function fpsUpdate() {
    fpsOutput.innerHTML = fpsAverage.toFixed(2);
}

function frameDraw() {
    if(drawing) { return; } else { drawing = true; }

    timeCurrent = Date.now();
    var fpsThisFrame = 1000 / (timeCurrent - timeLast);
    if(timeCurrent > timeLast) {
        fpsAverage += (fpsThisFrame - fpsAverage) / fpsFilter;
        timeLast = timeCurrent;
    }

    drawing = false;
}

setInterval(fpsUpdate, 1000);
fpsUpdate();

setInterval(frameDraw, 1000 / fpsDesired);
frameDraw();

このスレッドはGoogleの結果の上位にあるので、いじくり回して、もっとスムーズなものを思い付くことができるかどうかを確認します。

私たち全員がチームとして何を考え出すことができるかを見てみましょう。サードパーティのライブラリを使用しないことは常に適切であり、コードを誰にとっても移植可能にすることができます:)

-プラティマ

2
user2552832

毎秒fpsカウンターをリセットする間隔を設定するだけです。

var fpsOut, fpsCount;

var draw = function () {

    fpsCount++;

    ..Draw To Canvas..


    ..Get the fps value: fpsOut

    requestAnimationFrame(draw);

};
setInterval(function () {

    fpsOut = fpsCount;
    fpsCount = 0;

}, 1000);

draw();
1
Gustav G