我知道之前有一些问题像以前一样被提出过,例如: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);
}
我是否正确将setTimeout函数设置为1毫秒的速度?我以为这会让它尽可能快地循环。
我应该每隔100帧计算一次,找出运行100帧所花费的毫秒数,然后进行计算以找出毫秒数为1000时应该完成的帧数?这个计算是什么?
为了让结果更准确,我猜我需要显示平均值,因为一帧可以变化很大,我应该怎么做?
非常感谢任何提示。
感谢。
答案 0 :(得分:23)
请注意,更新输出的速度越快,对测量的影响就越大。虽然很小,但我尝试每秒更新一次fps输出或更少,除非有必要加快速度。
我喜欢对我的结果进行低通滤波,以便临时打嗝不会太强烈地影响值。这比移动平均值更容易计算和写入,并且没有总体平均值的问题,即“当前”读数会受到整个运行期间总体性能的影响(例如,启动期间的异常读数)。
总之,这是我通常测量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);
答案 1 :(得分: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);
答案 2 :(得分:2)
我已经发布了解决方案并对其进行了一些改进。看看这里 - http://jsfiddle.net/ync3S/
主要栏目如下:
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();
要修补一下,看看我能否提出更顺畅的东西,因为这个帖子在谷歌搜索结果中接近顶部。
让我们看看我们作为一个团队能够提出什么,而且我认为不使用第三方库总是很好,使得代码可以移植给所有人:)
-Platima
答案 3 :(得分: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();
答案 4 :(得分: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);