## JavaScript FPS Counter

A side project called for a JavaScript FPS counter, here’s how I did it.

I know Chrome has an FPS counter but it only counts something as a frame when something actually changes, so on a page that isn’t doing anything the FPS would drop to less than 60.

Before implementing my FPS counter I looked at [this question](https://stackoverflow.com/q/8279729/1156119) on Stack Overflow where this was the most up voted answer:

```
var lastCalledTime;
var fps;

function requestAnimFrame() {

if(!lastCalledTime) {
     lastCalledTime = Date.now();
     fps = 0;
     return;
  }
  delta = (Date.now() - lastCalledTime)/1000;
  lastCalledTime = Date.now();
  fps = 1/delta;
}
```

While definitely fast, this solution suffers by having the number be very unstable and jumping between 59/60 pretty much every frame, making it very difficult to read. It also only measures over the last frame, meaning if there was a very long frame that took 500ms in between frames of 1ms, the FPS counter would change to read “2 FPS” for only a single frame (about 16ms) before shooting back up to “60 FPS”.

A nicer solution turns out to be just as simple:

```
const times = [];
let fps;

function refreshLoop() {
  window.requestAnimationFrame(() => {
    const now = performance.now();
    while (times.length > 0 && times[0] <= now - 1000) {
      times.shift();
    }
    times.push(now);
    fps = times.length;
    refreshLoop();
  });
}

refreshLoop();
```

It works by using `window.requestAnimationFrame` to fire the function `refreshLoop` every animation frame. The `refreshLoop` function adds the current timestamp value to the queue `times` and removes any timestamps that occurred more than a second ago from the front of the queue. Since `performance.now()` always increases in value, the queue `times` should always be sorted. The FPS is then calculated by counting the size of the queue.

This met my needs perfectly but it could be improved in a few ways:

- By only updating the FPS display every 500ms
- Use a circular list for the queue if GC’s caused by the queue are a concern

Another option is to go with an existing project like [stats.js](https://github.com/mrdoob/stats.js/) which has some additional features like a nice display and memory tracking.
