Javascript 检查JS中的FPS?
如何检查javascript的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);
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
)。您可以通过bailingif(thisLoop==lastLoop)对此进行保护
。但是,请注意,如果您使用的过滤器强度为1
,则使用过滤器毫无意义。只需使用@SLaks-answer即可。@Phrogz我知道我参加聚会有点晚了。。但即使我使用您建议的防护措施来防止无限fps错误。我仍然会得到无限fps?有任何建议吗?您可以按日期替换新日期。现在(),同样的事情,但更正确的是,如何根据实际fps刷新函数gameLoop()?因为在使用setInterval()时,我只能传递时间间隔的参数一次。@JacekDziurdzikowski:CallsetTimeout()
每次安排下一帧。@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)
}
);