14

我知道以前有人问过这样的问题,例如:Check FPS in JS? - 在某种程度上确实有效,我能够找出每个循环需要多长时间才能完成。

我正在寻找的是更具可读性和可控性的东西。我希望能够为 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. 为了使结果更准确,我猜我需要显示平均值,因为一帧可能会有很大的变化,我应该怎么做?

非常感谢任何提示。

谢谢。

4

5 回答 5

23
  1. 请注意,更新输出的速度越快,对测量的影响就越大。虽然很少,但我尝试每秒更新一次或更少的 fps 输出,除非需要更快。

  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); 
于 2011-02-22T14:05:55.407 回答
3

我尝试了一些东西,

如果你改变

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); 
于 2011-11-11T15:20:04.157 回答
2

我已经发布了解决方案并对其进行了一些改进。看看这里 - 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();

要去修修补补,看看我能不能想出一些更流畅的东西,因为这个线程在谷歌结果中接近顶部。

让我们看看我们作为一个团队都能想出什么,我认为不使用 3rd 方库总是很整洁,使代码对任何人都可移植:)

-普拉蒂玛

于 2014-03-24T10:48:48.227 回答
1

只需设置一个每秒重置 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();
于 2016-05-04T08:55:50.543 回答
0

如果您想要实时更新,请考虑让它一次又一次地实时循环。为了减少对性能的影响,只更新受控变量,在本例中为 FPS。你可以有可选的帧延迟,我会放在这里,以防万一。只需根据您的需要复制、粘贴和调整代码。

请注意,单帧持续 16.66 毫秒。

setInterval(function(){var latencybase1 = parseFloat(new Date().getTime());
var latencybase2 = parseFloat(new Date().getTime());
var latency = latencybase2-latencybase1;
var fps = Math.round(1000/latency);

if (latency<16.66) 
{document.getElementById("FPS").innerHTML = fps+" 
FPS";}
else {document.getElementById("FPS").innerHTML = ""+fps+" FPS";}
document.getElementById("Latency").innerHTML = latency+" ms";}, 0);
于 2020-10-11T00:24:00.733 回答