requestAnimationFrameでFPSモニタリングを実装する

問題

Webアプリでアニメーションやリアルタイムデータ更新がカクつくのに、実際のFPSがどの程度出ているか測定する方法が必要です。

解決方法

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; }
}

ポイント

  • requestAnimationFrameはブラウザが次の画面を描画する直前に呼ばれます。1秒に60回呼ばれれば60fpsです。
  • 1秒ごとにフレーム数を数えてFPSを計算します。一時的なドロップは無視し、3秒連続で30fps未満の場合のみ警告すれば誤検知が減ります。
  • performance.now()Date.now()より精密です。マイクロ秒単位なのでFPS計算に適しています。