Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 Canvas performance - calculating loops/frames per second

I know a few questions have been asked like this one before, such as this: Check FPS in JS? - which did work to some degree, I was able to find out how long each loop took to complete.

What I am looking for though is something more readable and controllable. I want to be able to set the refresh rate for the FPS counter to make it slow so it is human readable or as fast as the application can run, so I can use it on some kind of speedometer.

Anyway so here is the code I have right now:

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. Am I right to be setting the setTimeout function to a speed of 1 millisecond? I was thinking this will just make it loop as fast as it possibly can.

  2. Should I count every 100 frames or so, find out how many milliseconds it took to run 100 frames then make a calculation to find out how many frames it would have done if the milliseconds were 1000? What would this calculation be?

  3. To make the result more accurate I am guessing I need to display averages as one frame can vary a significant amount, how should I do this?

Any tips are greatly appreciated.

Thanks.

like image 476
Sabai Avatar asked Feb 22 '11 13:02

Sabai


People also ask

How fast is html5 canvas?

The Canvas tab loaded in one second and takes up 30MB. It also takes up 13% of CPU time all of the time, regardless of whether or not one is looking at it. Video on the HTML page, while I am not moving objects, is actually perfectly smooth.

Is canvas faster than HTML?

Canvas would be better for faster things and heavy bitmap manipulation (like animation), but will take more code if you want lots of interactivity. I've run a bunch of numbers on HTML DIV-made drawing versus Canvas-made drawing.

Is canvas more performant?

In short, the canvas and WebGL are more performant than the DOM, and with third-party libraries, its ease-of-use is comparable; furthermore, growing browser support for additional web standards have the potential to further boost canvas performance.

How do you use frames per second in a drawing function?

All we do is set our frames per second and intervals between each frame. In the drawing function we deduct our last frame’s execution time from the current time to check whether the time elapsed since the last frame is more than our interval (which is based on the fps) or not.

How do I improve the performance of the HTML5 canvas?

Switch off perfect drawing-In some cases the result of drawing with the HTML5 canvas is not what you might have expected-see the demo for an example Disable Perfect Drawing. Konva does extra work via its perfect drawing feature to put that right, but this comes with a performance cost. By setting shape.

How to get last frame’s execution time from the current time?

Just a proof of concept. Very simple code. All we do is set our frames per second and intervals between each frame. In the drawing function we deduct our last frame’s execution time from the current time to check whether the time elapsed since the last frame is more than our interval (which is based on the fps) or not.

Is it possible to measure framerate with the performance API?

This makes it especially useless for framerate measurements, where one 60Hz frame needs ~17ms. The Performance API has been specificly made for such use cases and can be used equivalently to new Date (). Just take one of the other answers and replace new Date () with performance.now (), and you are ready to go.


1 Answers

  1. Note that the faster you update your output, the more you will affect your measurement. Although minimal, I try to update my fps output once per second or less unless it's necessary to go faster.

  2. I like to have a low-pass filter on my results so that a temporary hiccup doesn't affect the values too strongly. This is easier to compute and write than a moving average, and doesn't have the problem of an overall average where your 'current' readings are affected by total performance over the entire run (e.g. anomalous readings during startup).

Put together, here's how I usually measure 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); 
like image 129
Phrogz Avatar answered Sep 21 '22 03:09

Phrogz