Build an FPS Monitor with requestAnimationFrame
Problem
Web app animations or real-time updates feel sluggish, but there’s no way to measure the actual FPS.
Solution
class FPSMonitor {
constructor(onLowFPS) {
this.frameCount = 0;
this.lastTime = performance.now();
this.lowFpsCount = 0;
this.onLowFPS = onLowFPS;
this.running = false;
}
start() {
this.running = true;
this.tick();
}
tick() {
if (!this.running) return;
this.frameCount++;
const now = performance.now();
const delta = now - this.lastTime;
if (delta >= 1000) {
const fps = Math.round((this.frameCount * 1000) / delta);
if (fps < 30) {
this.lowFpsCount++;
if (this.lowFpsCount >= 3) this.onLowFPS(fps);
} else {
this.lowFpsCount = 0;
}
this.frameCount = 0;
this.lastTime = now;
}
requestAnimationFrame(() => this.tick());
}
stop() { this.running = false; }
}
Key Points
requestAnimationFramefires just before the browser paints the next frame. 60 calls per second = 60fps.- Count frames per second to calculate FPS. Alerting only after 3 consecutive seconds below 30fps reduces false positives.
performance.now()is more precise thanDate.now()— microsecond resolution is ideal for FPS measurement.